|
|
|
@ -14,36 +14,17 @@ import {ERC721} from "solmate/tokens/ERC721.sol";
|
|
|
|
|
import {Owned} from "solmate/auth/Owned.sol";
|
|
|
|
|
import {LibString} from "solmate/utils/LibString.sol";
|
|
|
|
|
|
|
|
|
|
import {Boomer} from "./Boomer.sol";
|
|
|
|
|
import {Unaboomer} from "./Unaboomer.sol";
|
|
|
|
|
import {Mailbomb} from "./Mailbomb.sol";
|
|
|
|
|
|
|
|
|
|
error NotEnoughEther();
|
|
|
|
|
error NotOwnerOfToken();
|
|
|
|
|
error MaxSupplyReached();
|
|
|
|
|
error TooMany();
|
|
|
|
|
error NoContract();
|
|
|
|
|
error WrongEtherAmount();
|
|
|
|
|
error MaxAmountReached();
|
|
|
|
|
error NoAdmins();
|
|
|
|
|
error NotAdmin();
|
|
|
|
|
error NoRemoveSelf();
|
|
|
|
|
error NoRemoveDeployer();
|
|
|
|
|
error NotEnoughBombs();
|
|
|
|
|
contract UnaboomerCommon is Owned {
|
|
|
|
|
|
|
|
|
|
// mintBoomer
|
|
|
|
|
// mintBomb
|
|
|
|
|
// mailBombs
|
|
|
|
|
uint256 public boomerPrice = 0.01 ether;
|
|
|
|
|
uint256 public bombPrice = 0.01 ether;
|
|
|
|
|
Unaboomer public unaboomer;
|
|
|
|
|
Mailbomb public mailbomb;
|
|
|
|
|
|
|
|
|
|
contract Unaboomer is Owned {
|
|
|
|
|
using LibString for uint256;
|
|
|
|
|
|
|
|
|
|
uint256 public price = 0.01 ether;
|
|
|
|
|
uint256 public minted;
|
|
|
|
|
string public baseURI;
|
|
|
|
|
|
|
|
|
|
Unaboomer public UnaboomerContract;
|
|
|
|
|
|
|
|
|
|
constructor() ERC721("Mailbomb", "BOMB") Owned(msg.sender) {}
|
|
|
|
|
constructor() Owned(msg.sender) {}
|
|
|
|
|
|
|
|
|
|
// =========================================================================
|
|
|
|
|
// Admin
|
|
|
|
@ -56,59 +37,70 @@ contract Unaboomer is Owned {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Set price for 1 BOMB
|
|
|
|
|
function setPrice(uint256 _price) external onlyOwner {
|
|
|
|
|
price = _price;
|
|
|
|
|
function setBombPrice(uint256 _price) external onlyOwner {
|
|
|
|
|
bombPrice = _price;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Set metadata URI for alive BOOMR
|
|
|
|
|
function setBaseURI(string calldata _baseURI) external onlyOwner {
|
|
|
|
|
baseURI = _baseURI;
|
|
|
|
|
/// Set price for 1 BOOMR
|
|
|
|
|
function setBoomerPrice(uint256 _price) external onlyOwner {
|
|
|
|
|
boomerPrice = _price;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Set contract address for Unaboomer tokens
|
|
|
|
|
function setUnaboomerContract(address _address) external onlyOwner {
|
|
|
|
|
UnaboomerContract = Unaboomer(_address);
|
|
|
|
|
unaboomer = Unaboomer(_address);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Set contract address for Mailbomb tokens
|
|
|
|
|
function setUnaboomerContract(address _address) external onlyOwner {
|
|
|
|
|
mailbomb = Unaboomer(_address);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// =========================================================================
|
|
|
|
|
// Tokens
|
|
|
|
|
// =========================================================================
|
|
|
|
|
|
|
|
|
|
function assembleBomb(uint256 _amount) external payable {
|
|
|
|
|
if (msg.value < _amount * price) revert NotEnoughEther();
|
|
|
|
|
unchecked {
|
|
|
|
|
for (uint256 i; i < _amount; i++) {
|
|
|
|
|
_mint(msg.sender, minted + 1);
|
|
|
|
|
minted++;
|
|
|
|
|
/// Radicalize a boomer to become a Unaboomer
|
|
|
|
|
function radicalizeBoomer(uint256 _amount) external payable {
|
|
|
|
|
// check if game halted
|
|
|
|
|
require(msg.value >= _amount * boomerPrice, "not enough ether");
|
|
|
|
|
unaboomer.mint(msg.sender, _amount);
|
|
|
|
|
mailbomb.mint(msg.sender, _amount * 2);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Assemble additional mailbombs to kill targets
|
|
|
|
|
function assembleBomb(uint256 _amount) external payable {
|
|
|
|
|
// 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 considered a dud.
|
|
|
|
|
/// 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 mailBombs(uint256[] calldata tokenIds) external returns (bool[] memory results) {
|
|
|
|
|
if (tokenIds.length > balanceOf(msg.sender)) revert NotEnoughBombs();
|
|
|
|
|
function sendBombs(uint256[] calldata tokenIds) external returns (bool[] memory results) {
|
|
|
|
|
require(tokenIds.length <= mailbomb.balanceOf(msg.sender));
|
|
|
|
|
bool[] memory res = new bool[](tokenIds.length);
|
|
|
|
|
uint256 boomerSupply = UnaboomerContract.totalSupply();
|
|
|
|
|
uint256 boomerSupply = unaboomer.totalSupply();
|
|
|
|
|
for (uint256 i; i < tokenIds.length; i++) {
|
|
|
|
|
if (ownerOf(tokenIds[i]) != msg.sender) revert NotOwnerOfToken();
|
|
|
|
|
require(mailbomb.ownerOf(tokenIds[i]) == msg.sender, "token not owned");
|
|
|
|
|
uint256 randomBoomer = uint256(keccak256(abi.encodePacked(tokenIds[i], block.timestamp, msg.sender))) % boomerSupply;
|
|
|
|
|
_burn(tokenIds[i]);
|
|
|
|
|
bool _res = UnaboomerContract.killBoomer(randomBoomer);
|
|
|
|
|
mailbomb._burn(tokenIds[i]);
|
|
|
|
|
bool _res = killBoomer(randomBoomer);
|
|
|
|
|
res[i] = _res;
|
|
|
|
|
}
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function totalSupply() view public returns (uint256 supply) {
|
|
|
|
|
return minted;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function tokenURI(uint256 _tokenId) public view override returns (string memory) {
|
|
|
|
|
return string(abi.encodePacked(baseURI, _tokenId.toString(), ".json"));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function supportsInterface(bytes4 interfaceId) public view virtual override (ERC721) returns (bool) {
|
|
|
|
|
return super.supportsInterface(interfaceId);
|
|
|
|
|
}
|