CommunityERC721.t.sol
1 // SPDX-License-Identifier: UNLICENSED 2 pragma solidity ^0.8.17; 3 4 import { Test } from "forge-std/Test.sol"; 5 import { DeployOwnerAndMasterToken } from "../script/DeployOwnerAndMasterToken.s.sol"; 6 import { DeploymentConfig } from "../script/DeploymentConfig.s.sol"; 7 import { CommunityOwnable } from "../contracts/CommunityOwnable.sol"; 8 import { BaseToken } from "../contracts/tokens/BaseToken.sol"; 9 import { OwnerToken } from "../contracts/tokens/OwnerToken.sol"; 10 import { MasterToken } from "../contracts/tokens/MasterToken.sol"; 11 import { CommunityERC721 } from "../contracts/tokens/CommunityERC721.sol"; 12 13 contract CommunityERC721Test is Test { 14 CommunityERC721 internal collectibleV1; 15 16 address internal deployer; 17 address[] internal accounts = new address[](4); 18 19 string internal name = "Test"; 20 string internal symbol = "TEST"; 21 string internal baseURI = "http://local.dev"; 22 uint256 internal maxSupply = 4; 23 bool internal remoteBurnable = true; 24 bool internal transferable = true; 25 26 function setUp() public virtual { 27 DeployOwnerAndMasterToken deployment = new DeployOwnerAndMasterToken(); 28 (OwnerToken ownerToken, MasterToken masterToken, DeploymentConfig deploymentConfig) = deployment.run(); 29 deployer = deploymentConfig.deployer(); 30 31 collectibleV1 = new CommunityERC721( 32 name, symbol, maxSupply, remoteBurnable, transferable, baseURI, address(ownerToken), address(masterToken) 33 ); 34 35 accounts[0] = makeAddr("one"); 36 accounts[1] = makeAddr("two"); 37 accounts[2] = makeAddr("three"); 38 accounts[3] = makeAddr("four"); 39 } 40 } 41 42 contract DeploymentTest is CommunityERC721Test { 43 function test_Deployment() public { 44 assertEq(collectibleV1.name(), name); 45 assertEq(collectibleV1.symbol(), symbol); 46 assertEq(collectibleV1.maxSupply(), maxSupply); 47 assertEq(collectibleV1.remoteBurnable(), remoteBurnable); 48 assertEq(collectibleV1.transferable(), transferable); 49 assertEq(collectibleV1.baseTokenURI(), baseURI); 50 } 51 } 52 53 contract MintToTest is CommunityERC721Test { 54 event StatusMint(address indexed from, address indexed to, uint256 indexed tokenId); 55 56 function setUp() public virtual override { 57 CommunityERC721Test.setUp(); 58 } 59 60 function test_RevertWhen_SenderIsNotOwner() public { 61 vm.expectRevert(CommunityOwnable.CommunityOwnable_NotAuthorized.selector); 62 collectibleV1.mintTo(accounts); 63 } 64 65 function test_RevertWhen_MaxSupplyIsReached() public { 66 vm.startPrank(deployer); 67 collectibleV1.mintTo(accounts); 68 69 address[] memory otherAddresses = new address[](1); 70 otherAddresses[0] = makeAddr("anotherAccount"); 71 vm.expectRevert(BaseToken.BaseToken_MaxSupplyReached.selector); 72 collectibleV1.mintTo(otherAddresses); 73 74 assertEq(collectibleV1.maxSupply(), maxSupply); 75 assertEq(collectibleV1.totalSupply(), maxSupply); 76 } 77 78 function test_MintTo() public { 79 uint256 length = accounts.length; 80 for (uint8 i = 0; i < length; i++) { 81 assertEq(collectibleV1.balanceOf(accounts[i]), 0); 82 } 83 vm.prank(deployer); 84 for (uint8 i = 0; i < length; i++) { 85 vm.expectEmit(true, true, true, true); 86 emit StatusMint(address(0), accounts[i], i); 87 } 88 collectibleV1.mintTo(accounts); 89 for (uint8 i = 0; i < length; i++) { 90 assertEq(collectibleV1.balanceOf(accounts[i]), 1); 91 } 92 } 93 } 94 95 contract RemoteBurnTest is CommunityERC721Test { 96 function setUp() public virtual override { 97 CommunityERC721Test.setUp(); 98 } 99 100 function test_RevertWhen_SenderIsNotOwner() public { 101 uint256[] memory ids = new uint256[](1); 102 ids[0] = 0; 103 vm.expectRevert(CommunityOwnable.CommunityOwnable_NotAuthorized.selector); 104 collectibleV1.remoteBurn(ids); 105 } 106 107 function test_RemoteBurn() public { 108 vm.startPrank(deployer); 109 collectibleV1.mintTo(accounts); 110 111 assertEq(collectibleV1.totalSupply(), maxSupply); 112 113 uint256[] memory ids = new uint256[](1); 114 ids[0] = 0; 115 collectibleV1.remoteBurn(ids); 116 117 assertEq(collectibleV1.balanceOf(accounts[0]), 0); 118 assertEq(collectibleV1.totalSupply(), maxSupply - 1); 119 } 120 } 121 122 contract SafeBatchTransferFromTest is CommunityERC721Test { 123 function setUp() public virtual override { 124 CommunityERC721Test.setUp(); 125 } 126 127 function test_RevertWhen_ReceiversAndIdsMismatch() public { 128 // ensure sender owns a token 129 vm.prank(deployer); 130 collectibleV1.mintTo(accounts); 131 132 address[] memory receivers = new address[](1); 133 receivers[0] = accounts[1]; 134 135 // ids must be of same length as `receivers` 136 uint256[] memory ids = new uint256[](2); 137 ids[0] = 0; 138 ids[1] = 1; 139 140 vm.prank(accounts[0]); 141 vm.expectRevert(BaseToken.BaseToken_ReceiversAndIdsMismatch.selector); 142 collectibleV1.safeBatchTransferFrom(accounts[0], receivers, ids, ""); 143 } 144 145 function test_RevertWhen_NotAuthorized() public { 146 vm.prank(deployer); 147 collectibleV1.mintTo(accounts); 148 149 address[] memory receivers = new address[](1); 150 receivers[0] = accounts[3]; 151 152 // ids must be of same length as `accounts` 153 uint256[] memory ids = new uint256[](1); 154 ids[0] = 0; 155 156 // ensure accounts[3] has no ownership or approval of token with id `0` 157 assertEq(collectibleV1.ownerOf(ids[0]), accounts[0]); 158 assertEq(collectibleV1.isApprovedForAll(accounts[0], receivers[0]), false); 159 160 vm.prank(receivers[0]); 161 vm.expectRevert(bytes("ERC721: caller is not token owner or approved")); 162 collectibleV1.safeBatchTransferFrom(accounts[0], receivers, ids, ""); 163 } 164 165 function test_RevertWhen_ReceiverAddressIsZero() public { 166 // ensure sender owns a token 167 vm.prank(deployer); 168 collectibleV1.mintTo(accounts); 169 170 address[] memory receivers = new address[](1); 171 receivers[0] = address(0); 172 173 uint256[] memory ids = new uint256[](1); 174 ids[0] = 0; 175 176 vm.prank(accounts[0]); 177 vm.expectRevert(bytes("ERC721: transfer to the zero address")); 178 collectibleV1.safeBatchTransferFrom(accounts[0], receivers, ids, ""); 179 } 180 181 function test_SafeBatchTransferFrom() public { 182 // ensure sender owns a token 183 vm.prank(deployer); 184 address[] memory sameAddresses = new address[](3); 185 sameAddresses[0] = accounts[0]; 186 sameAddresses[1] = accounts[0]; 187 sameAddresses[2] = accounts[0]; 188 collectibleV1.mintTo(sameAddresses); 189 190 address[] memory receivers = new address[](3); 191 receivers[0] = accounts[1]; 192 receivers[1] = accounts[2]; 193 receivers[2] = accounts[3]; 194 195 uint256[] memory ids = new uint256[](3); 196 ids[0] = 0; 197 ids[1] = 1; 198 ids[2] = 2; 199 200 vm.prank(accounts[0]); 201 collectibleV1.safeBatchTransferFrom(accounts[0], receivers, ids, ""); 202 203 assertEq(collectibleV1.balanceOf(accounts[0]), 0); 204 assertEq(collectibleV1.balanceOf(accounts[1]), 1); 205 assertEq(collectibleV1.balanceOf(accounts[2]), 1); 206 assertEq(collectibleV1.balanceOf(accounts[3]), 1); 207 } 208 209 function test_SafeBatchTransferFromToSingleReceiver() public { 210 // ensure sender owns a token 211 vm.prank(deployer); 212 address[] memory sameAddresses = new address[](3); 213 sameAddresses[0] = accounts[0]; 214 sameAddresses[1] = accounts[0]; 215 sameAddresses[2] = accounts[0]; 216 collectibleV1.mintTo(sameAddresses); 217 218 address[] memory receivers = new address[](3); 219 receivers[0] = accounts[1]; 220 receivers[1] = accounts[1]; 221 receivers[2] = accounts[1]; 222 223 uint256[] memory ids = new uint256[](3); 224 ids[0] = 0; 225 ids[1] = 1; 226 ids[2] = 2; 227 228 vm.prank(accounts[0]); 229 collectibleV1.safeBatchTransferFrom(accounts[0], receivers, ids, ""); 230 231 assertEq(collectibleV1.balanceOf(accounts[0]), 0); 232 assertEq(collectibleV1.balanceOf(accounts[1]), 3); 233 } 234 } 235 236 contract NotTransferableTest is CommunityERC721Test { 237 function setUp() public virtual override { 238 DeployOwnerAndMasterToken deployment = new DeployOwnerAndMasterToken(); 239 (OwnerToken ownerToken, MasterToken masterToken, DeploymentConfig deploymentConfig) = deployment.run(); 240 deployer = deploymentConfig.deployer(); 241 242 collectibleV1 = new CommunityERC721( 243 name, symbol, maxSupply, remoteBurnable, false, baseURI, address(ownerToken), address(masterToken) 244 ); 245 246 accounts[0] = makeAddr("one"); 247 accounts[1] = makeAddr("two"); 248 accounts[2] = makeAddr("three"); 249 accounts[3] = makeAddr("four"); 250 } 251 252 function test_RevertWhen_TokenIsNotTransferable() public { 253 // ensure accounts own tokens 254 vm.prank(deployer); 255 collectibleV1.mintTo(accounts); 256 uint256[] memory ids = new uint256[](4); 257 ids[0] = 0; 258 ids[1] = 1; 259 ids[2] = 2; 260 ids[3] = 3; 261 262 vm.prank(accounts[0]); 263 vm.expectRevert(BaseToken.BaseToken_NotTransferable.selector); 264 collectibleV1.safeBatchTransferFrom(accounts[0], accounts, ids, ""); 265 } 266 }