save progress

master
lza_menace 2 years ago
parent 4393670e6d
commit 0dff11698c

@ -31,11 +31,9 @@ error NotEnoughBombs();
contract Mailbomb is ERC721, Owned { contract Mailbomb is ERC721, Owned {
using LibString for uint256; using LibString for uint256;
uint256 public price = 0.01 ether;
uint256 public minted; uint256 public minted;
string public baseURI; string public baseURI;
UnaboomerCommon public main;
Unaboomer public UnaboomerContract;
constructor() ERC721("Mailbomb", "BOMB") Owned(msg.sender) {} constructor() ERC721("Mailbomb", "BOMB") Owned(msg.sender) {}
@ -49,53 +47,32 @@ contract Mailbomb is ERC721, Owned {
payable(msg.sender).transfer(balance); payable(msg.sender).transfer(balance);
} }
/// Set price for 1 BOMB
function setPrice(uint256 _price) external onlyOwner {
price = _price;
}
/// Set metadata URI for alive BOOMR /// Set metadata URI for alive BOOMR
function setBaseURI(string calldata _baseURI) external onlyOwner { function setBaseURI(string calldata _baseURI) external onlyOwner {
baseURI = _baseURI; baseURI = _baseURI;
} }
/// Set contract address for Unaboomer tokens /// Set main contract address for executing functions
function setUnaboomerContract(address _address) external onlyOwner { function setMainContract(address _address) external onlyOwner {
UnaboomerContract = Unaboomer(_address); main = UnaboomerCommon(_address);
} }
// ========================================================================= // =========================================================================
// Tokens // Tokens
// ========================================================================= // =========================================================================
function assembleBomb(uint256 _amount) external payable { /// Mint tokens from main contract
if (msg.value < _amount * price) revert NotEnoughEther(); function mint(address _to, uint256 _amount) external payable {
require(msg.sender == address(main), "invalid minter");
unchecked { unchecked {
for (uint256 i; i < _amount; i++) { for (uint256 i; i < _amount; i++) {
_mint(msg.sender, minted + 1);
minted++; minted++;
_mint(to, minted);
} }
} }
} }
/// Send N bombs to pseudo-random Unaboomer tokenIds to potentially kill them. function totalSupply() public view returns (uint256 supply) {
/// If the Unaboomer is already dead, the bomb is considered 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();
bool[] memory res = new bool[](tokenIds.length);
uint256 boomerSupply = UnaboomerContract.totalSupply();
for (uint256 i; i < tokenIds.length; i++) {
if (ownerOf(tokenIds[i]) != msg.sender) revert NotOwnerOfToken();
uint256 randomBoomer = uint256(keccak256(abi.encodePacked(tokenIds[i], block.timestamp, msg.sender))) % boomerSupply;
_burn(tokenIds[i]);
bool _res = UnaboomerContract.killBoomer(randomBoomer);
res[i] = _res;
}
return res;
}
function totalSupply() view public returns (uint256 supply) {
return minted; return minted;
} }

@ -13,31 +13,18 @@ chaos ensues until 1000 survivors - the game stops
import {ERC721} from "solmate/tokens/ERC721.sol"; import {ERC721} from "solmate/tokens/ERC721.sol";
import {Owned} from "solmate/auth/Owned.sol"; import {Owned} from "solmate/auth/Owned.sol";
import {LibString} from "solmate/utils/LibString.sol"; import {LibString} from "solmate/utils/LibString.sol";
import {Mailbomb} from "./Mailbomb.sol"; import {UnaboomerCommon} from "./UnaboomerCommon.sol";
error NotEnoughEther(); contract Unaboomer is ERC721, Owned {
error NotOwnerOfToken();
error MaxSupplyReached();
error TooMany();
error NoContract();
error WrongEtherAmount();
error MaxAmountReached();
error NoAdmins();
error NotAdmin();
error NoRemoveSelf();
error NoRemoveDeployer();
contract Boomer is ERC721, Owned {
using LibString for uint256; using LibString for uint256;
mapping(uint256 => bool) public tokenDead; mapping(uint256 => bool) public tokenDead;
uint256 public constant MAX_SUPPLY = 10000; uint256 public constant MAX_SUPPLY = 10000;
uint256 public price = 0.01 ether;
uint256 public minted; uint256 public minted;
string public aliveURI; string public aliveURI;
string public deadURI; string public deadURI;
Mailbomb public MailbombContract; UnaboomerCommon public main;
constructor() ERC721("Unaboomer", "BOOMR") Owned(msg.sender) {} constructor() ERC721("Unaboomer", "BOOMR") Owned(msg.sender) {}
@ -51,11 +38,6 @@ contract Boomer is ERC721, Owned {
payable(msg.sender).transfer(balance); payable(msg.sender).transfer(balance);
} }
/// Set price for PFP + 2 BOMB
function setPrice(uint256 _price) external onlyOwner {
price = _price;
}
/// Set metadata URI for alive BOOMR /// Set metadata URI for alive BOOMR
function setAliveURI(string calldata _baseURI) external onlyOwner { function setAliveURI(string calldata _baseURI) external onlyOwner {
aliveURI = _baseURI; aliveURI = _baseURI;
@ -66,39 +48,35 @@ contract Boomer is ERC721, Owned {
deadURI = _baseURI; deadURI = _baseURI;
} }
/// Set contract address for Mailbomb tokens /// Set main contract address for executing functions
function setMailbombContract(address _address) external onlyOwner { function setMainContract(address _address) external onlyOwner {
MailbombContract = Mailbomb(_address); main = UnaboomerCommon(_address);
}
/// Kill a Unaboomer with a mail bomb
/// @dev Function returns a boolean depending on if Boomer was already killed or not - aka if dud
function killBoomer(uint256 tokenId) external returns (bool isDud) {
require(msg.sender == address(MailbombContract), "Only Mailbomb contract can execute");
bool dud = tokenDead[tokenId];
tokenDead[tokenId] = true;
return dud;
} }
// ========================================================================= // =========================================================================
// Tokens // Tokens
// ========================================================================= // =========================================================================
function mint(uint256 _amount) external payable { /// Mint tokens from main contract
if (msg.sender == tx.origin) revert NoContract(); function mint(address _to, uint256 _amount) external payable {
if (_amount > 20) revert TooMany(); require(minted + _amount <= MAX_SUPPLY, "supply reached");
if (msg.value < _amount * price) revert NotEnoughEther(); require(msg.sender == address(main), "invalid minter");
if (minted + _amount > MAX_SUPPLY) revert MaxSupplyReached();
unchecked { unchecked {
for (uint256 i; i < _amount; i++) { for (uint256 i; i < _amount; i++) {
_mint(msg.sender, minted + 1);
minted++; minted++;
_mint(to, minted);
} }
} }
// also mint 2 BOMB to user
} }
function totalSupply() view public returns (uint256 supply) { /// Toggle token state from living to dead
function kill(uint256 tokenId) external {
require(msg.sender == address(main), "invalid minter");
require(tokenId < minted, "invalid token id");
tokenDead[tokenId] = true;
}
function totalSupply() public view returns (uint256 supply) {
return minted; return minted;
} }

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