From b891eca8786c7432a7da68cf22ab8d1f76340690 Mon Sep 17 00:00:00 2001 From: lza_menace Date: Fri, 23 Dec 2022 07:39:46 -0800 Subject: [PATCH] use new ownership mechanics --- cache/solidity-files-cache.json | 50 +++------------------------------ src/Unaboomer.sol | 50 +++++++++++++++++++++------------ test/Unaboomer.t.sol | 30 ++++++++++++++++---- 3 files changed, 60 insertions(+), 70 deletions(-) diff --git a/cache/solidity-files-cache.json b/cache/solidity-files-cache.json index 7b435dd..099887c 100644 --- a/cache/solidity-files-cache.json +++ b/cache/solidity-files-cache.json @@ -668,46 +668,6 @@ } } }, - "lib/solmate/src/auth/Owned.sol": { - "lastModificationDate": 1671781956282, - "contentHash": "11fec455b72d2743b77d783d6017e1e9", - "sourceName": "lib/solmate/src/auth/Owned.sol", - "solcConfig": { - "settings": { - "optimizer": { - "enabled": true, - "runs": 200 - }, - "metadata": { - "bytecodeHash": "ipfs", - "appendCBOR": true - }, - "outputSelection": { - "*": { - "": [ - "ast" - ], - "*": [ - "abi", - "evm.bytecode", - "evm.deployedBytecode", - "evm.methodIdentifiers", - "metadata" - ] - } - }, - "evmVersion": "london", - "libraries": {} - } - }, - "imports": [], - "versionRequirement": ">=0.8.0", - "artifacts": { - "Owned": { - "0.8.17+commit.8df45f5f.Linux.gcc": "Owned.sol/Owned.json" - } - } - }, "lib/solmate/src/tokens/ERC721.sol": { "lastModificationDate": 1671781956286, "contentHash": "ecc06cefc5404b9e1adbc2e459d5757e", @@ -844,8 +804,8 @@ } }, "src/Unaboomer.sol": { - "lastModificationDate": 1671788224237, - "contentHash": "0b13a03c3451af69b934c9c135fa1ea2", + "lastModificationDate": 1671790962278, + "contentHash": "3bb83a689d676d73f129ece25cfb95a7", "sourceName": "src/Unaboomer.sol", "solcConfig": { "settings": { @@ -876,7 +836,6 @@ } }, "imports": [ - "lib/solmate/src/auth/Owned.sol", "lib/solmate/src/tokens/ERC721.sol", "lib/solmate/src/utils/LibString.sol" ], @@ -888,8 +847,8 @@ } }, "test/Unaboomer.t.sol": { - "lastModificationDate": 1671788116305, - "contentHash": "16626fed72f7b7cf459778574cb060a1", + "lastModificationDate": 1671790892439, + "contentHash": "eaffdb878938b0d9e0baf8a3e8d85285", "sourceName": "test/Unaboomer.t.sol", "solcConfig": { "settings": { @@ -934,7 +893,6 @@ "lib/forge-std/src/console.sol", "lib/forge-std/src/console2.sol", "lib/solmate/lib/ds-test/src/test.sol", - "lib/solmate/src/auth/Owned.sol", "lib/solmate/src/tokens/ERC721.sol", "lib/solmate/src/utils/LibString.sol", "src/Unaboomer.sol" diff --git a/src/Unaboomer.sol b/src/Unaboomer.sol index 60e3e95..172228d 100644 --- a/src/Unaboomer.sol +++ b/src/Unaboomer.sol @@ -11,7 +11,6 @@ chaos ensues until 1000 survivors - the game stops ********/ import {ERC721} from "solmate/tokens/ERC721.sol"; -import {Owned} from "solmate/auth/Owned.sol"; import {LibString} from "solmate/utils/LibString.sol"; error NotOwnerOfToken(); @@ -21,32 +20,39 @@ error NoContract(); error WrongEtherAmount(); error MaxAmountReached(); error NoAdmins(); +error NotAdmin(); +error NoRemoveSelf(); +error NoRemoveDeployer(); -contract Unaboomer is Owned, ERC721 { +contract Unaboomer is ERC721 { using LibString for uint256; - enum TokenState { - LIVING, - DEAD - } - - mapping(uint256 => TokenState) public tokenState; + mapping(uint256 => bool) public tokenDead; mapping(address => bool) public adminWallets; uint256 public constant MAX_SUPPLY = 10000; uint256 public minted; string public livingURI; string public deadURI; + address public deployer; address[] public payoutWallets; - constructor() ERC721("Unaboomer", "BOOMR") Owned(msg.sender) {} + constructor() ERC721("Unaboomer", "BOOMR") { + deployer = msg.sender; + adminWallets[msg.sender] = true; + } // ========================================================================= // Admin // ========================================================================= + modifier onlyAdmin { + if (adminWallets[msg.sender] == false) revert NotAdmin(); + _; + } + ///@dev Specify team wallets for payouts and contract administration - function updateAdmins(address[] calldata _admins) external onlyOwner { + function updateAdmins(address[] calldata _admins) external onlyAdmin { payoutWallets = _admins; for (uint256 i; i < _admins.length; i++) { adminWallets[_admins[i]] = true; @@ -54,19 +60,31 @@ contract Unaboomer is Owned, ERC721 { } ///@dev Remove admins if needed - function removeAdmin(address _admin) external onlyOwner { + function removeAdmin(address _admin) external onlyAdmin { + if (msg.sender == _admin) revert NoRemoveSelf(); + if (_admin == deployer) revert NoRemoveDeployer(); adminWallets[_admin] = false; } ///@dev Split payments to team - function withdraw() external onlyOwner { + function withdraw() external onlyAdmin { if (payoutWallets.length == 0) revert NoAdmins(); uint256 balance = address(this).balance; for (uint256 i; i < payoutWallets.length; i++) { - payable(payoutWallets[i]).transfer(balance / payoutWallets.length); + // payable(payoutWallets[i]).transfer(balance / payoutWallets.length); + (bool success, ) = payable(payoutWallets[i]).call{value: balance / payoutWallets.length}(""); + require(success, "failed to withdraw"); } } + function setLivingURI(string calldata _baseURI) external onlyAdmin { + livingURI = _baseURI; + } + + function setDeadURI(string calldata _baseURI) external onlyAdmin { + deadURI = _baseURI; + } + // ========================================================================= // Tokens // ========================================================================= @@ -87,12 +105,8 @@ contract Unaboomer is Owned, ERC721 { return minted; } - function setBaseURI(string calldata _baseURI) external onlyOwner { - livingURI = _baseURI; - } - function tokenURI(uint256 _tokenId) public view override returns (string memory) { - if (tokenState[_tokenId] == TokenState.LIVING) { + if (tokenDead[_tokenId] == false) { return string(abi.encodePacked(livingURI, _tokenId.toString(), ".json")); } else { return string(abi.encodePacked(deadURI, _tokenId.toString(), ".json")); diff --git a/test/Unaboomer.t.sol b/test/Unaboomer.t.sol index 8f1343d..6f00207 100644 --- a/test/Unaboomer.t.sol +++ b/test/Unaboomer.t.sol @@ -8,24 +8,42 @@ contract UnaboomerTest is Test { Unaboomer public boomr; address alice = address(1); address bob = address(2); + address[] admins = new address[](2); function setUp() public { boomr = new Unaboomer(); + admins[0] = address(1); + admins[1] = address(2); + boomr.updateAdmins(admins); } function testUpdatingAdmins() public { - address[] memory owners; - owners[0] = address(2); - owners[1] = address(3); - boomr.transferOwnership(address(1)); - startHoax(address(1)); - boomr.updateAdmins(owners); + // confirm admin on 1 and 2 + assertEq(boomr.adminWallets(boomr.deployer()), true); + assertEq(boomr.adminWallets(address(1)), true); assertEq(boomr.adminWallets(address(2)), true); + assertEq(boomr.adminWallets(address(3)), false); + hoax(address(1)); + boomr.removeAdmin(address(2)); + assertEq(boomr.adminWallets(address(2)), false); + hoax(address(2)); + vm.expectRevert(); + boomr.withdraw(); + } + + function testWithdraws() public { + // confirm payouts divvy equally + vm.deal(address(boomr), 11.5 ether); + vm.prank(address(1)); + boomr.withdraw(); + assertEq(address(1).balance, 5.75 ether); + assertEq(address(2).balance, 5.75 ether); } function testMint() public { vm.startPrank(alice); boomr.mint(5); assertEq(boomr.totalSupply(), 5); + assertEq(boomr.tokenDead(1), false); } }