CommunityTokenDeployer.t.sol
1 // SPDX-License-Identifier: UNLICENSED 2 pragma solidity ^0.8.17; 3 4 import { Test } from "forge-std/Test.sol"; 5 import { ECDSA } from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; 6 import { DeployContracts } from "../script/DeployContracts.s.sol"; 7 import { DeploymentConfig } from "../script/DeploymentConfig.s.sol"; 8 import { BaseTokenFactory } from "../contracts/factories/BaseTokenFactory.sol"; 9 import { OwnerToken } from "../contracts/tokens/OwnerToken.sol"; 10 import { MasterToken } from "../contracts/tokens/MasterToken.sol"; 11 import { CommunityOwnerTokenRegistry } from "../contracts/CommunityOwnerTokenRegistry.sol"; 12 import { CommunityTokenDeployer } from "../contracts/CommunityTokenDeployer.sol"; 13 14 contract CommunityTokenDeployerTest is Test { 15 DeploymentConfig internal deploymentConfig; 16 17 CommunityTokenDeployer internal tokenDeployer; 18 CommunityOwnerTokenRegistry internal tokenRegistry; 19 20 address internal deployer; 21 22 address internal immutable owner = makeAddr("owner"); 23 24 address internal communityAddress; 25 uint256 internal communityKey; 26 27 function setUp() public virtual { 28 DeployContracts deployment = new DeployContracts(); 29 (tokenDeployer, tokenRegistry,,, deploymentConfig) = deployment.run(); 30 deployer = deploymentConfig.deployer(); 31 (communityAddress, communityKey) = makeAddrAndKey("community"); 32 } 33 34 function test_Deployment() public { 35 assertEq(tokenDeployer.deploymentRegistry(), address(tokenRegistry)); 36 assertEq(tokenDeployer.owner(), deployer); 37 } 38 39 function _getOwnerTokenConfig() internal view returns (CommunityTokenDeployer.TokenConfig memory, bytes memory) { 40 ( 41 string memory ownerTokenName, 42 string memory ownerTokenSymbol, 43 string memory ownerTokenBaseURI, 44 bytes memory signerPublicKey 45 ) = deploymentConfig.ownerTokenConfig(); 46 47 CommunityTokenDeployer.TokenConfig memory ownerTokenConfig = 48 CommunityTokenDeployer.TokenConfig(ownerTokenName, ownerTokenSymbol, ownerTokenBaseURI); 49 return (ownerTokenConfig, signerPublicKey); 50 } 51 52 function _getMasterTokenConfig() internal view returns (CommunityTokenDeployer.TokenConfig memory) { 53 (string memory masterTokenName, string memory masterTokenSymbol, string memory masterTokenBaseURI,) = 54 deploymentConfig.masterTokenConfig(); 55 56 CommunityTokenDeployer.TokenConfig memory masterTokenConfig = 57 CommunityTokenDeployer.TokenConfig(masterTokenName, masterTokenSymbol, masterTokenBaseURI); 58 return masterTokenConfig; 59 } 60 61 function _createDeploymentSignature( 62 uint256 _signerKey, 63 address _signer, 64 address _deployer 65 ) 66 internal 67 view 68 returns (CommunityTokenDeployer.DeploymentSignature memory) 69 { 70 bytes32 digest = ECDSA.toTypedDataHash( 71 tokenDeployer.DOMAIN_SEPARATOR(), 72 keccak256(abi.encode(tokenDeployer.DEPLOYMENT_SIGNATURE_TYPEHASH(), _signer, _deployer)) 73 ); 74 (uint8 v, bytes32 r, bytes32 s) = vm.sign(_signerKey, digest); 75 return CommunityTokenDeployer.DeploymentSignature(_signer, _deployer, v, r, s); 76 } 77 } 78 79 contract SetDeploymentRegistryAddressTest is CommunityTokenDeployerTest { 80 event DeploymentRegistryAddressChange(address indexed); 81 82 function setUp() public virtual override { 83 CommunityTokenDeployerTest.setUp(); 84 } 85 86 function test_RevertWhen_SenderIsNotOwner() public { 87 vm.expectRevert(bytes("Ownable: caller is not the owner")); 88 tokenDeployer.setDeploymentRegistryAddress(makeAddr("someAddress")); 89 } 90 91 function test_RevertWhen_InvalidDeploymentRegistryAddress() public { 92 vm.prank(deployer); 93 vm.expectRevert(CommunityTokenDeployer.CommunityTokenDeployer_InvalidDeploymentRegistryAddress.selector); 94 tokenDeployer.setDeploymentRegistryAddress(address(0)); 95 } 96 97 function test_SetDeploymentRegistryAddress() public { 98 address newAddress = makeAddr("newAddress"); 99 vm.prank(deployer); 100 vm.expectEmit(true, true, true, true); 101 emit DeploymentRegistryAddressChange(newAddress); 102 tokenDeployer.setDeploymentRegistryAddress(newAddress); 103 104 assertEq(tokenDeployer.deploymentRegistry(), newAddress); 105 } 106 } 107 108 contract SetOwnerTokenFactoryAddressTest is CommunityTokenDeployerTest { 109 event OwnerTokenFactoryAddressChange(address indexed); 110 111 function setUp() public virtual override { 112 CommunityTokenDeployerTest.setUp(); 113 } 114 115 function test_RevertWhen_SenderIsNotOwner() public { 116 vm.expectRevert(bytes("Ownable: caller is not the owner")); 117 tokenDeployer.setOwnerTokenFactoryAddress(makeAddr("someAddress")); 118 } 119 120 function test_RevertWhen_InvalidTokenFactoryAddress() public { 121 vm.prank(deployer); 122 vm.expectRevert(CommunityTokenDeployer.CommunityTokenDeployer_InvalidTokenFactoryAddress.selector); 123 tokenDeployer.setOwnerTokenFactoryAddress(address(0)); 124 } 125 126 function test_SetOwnerTokenFactoryAddress() public { 127 address newAddress = makeAddr("newAddress"); 128 vm.prank(deployer); 129 vm.expectEmit(true, true, true, true); 130 emit OwnerTokenFactoryAddressChange(newAddress); 131 tokenDeployer.setOwnerTokenFactoryAddress(newAddress); 132 133 assertEq(tokenDeployer.ownerTokenFactory(), newAddress); 134 } 135 } 136 137 contract SetMasterTokenFactoryAddressTest is CommunityTokenDeployerTest { 138 event MasterTokenFactoryAddressChange(address indexed); 139 140 function setUp() public virtual override { 141 CommunityTokenDeployerTest.setUp(); 142 } 143 144 function test_RevertWhen_SenderIsNotOwner() public { 145 vm.expectRevert(bytes("Ownable: caller is not the owner")); 146 tokenDeployer.setMasterTokenFactoryAddress(makeAddr("someAddress")); 147 } 148 149 function test_RevertWhen_InvalidTokenFactoryAddress() public { 150 vm.prank(deployer); 151 vm.expectRevert(CommunityTokenDeployer.CommunityTokenDeployer_InvalidTokenFactoryAddress.selector); 152 tokenDeployer.setMasterTokenFactoryAddress(address(0)); 153 } 154 155 function test_SetOwnerTokenFactoryAddress() public { 156 address newAddress = makeAddr("newAddress"); 157 vm.prank(deployer); 158 vm.expectEmit(true, true, true, true); 159 emit MasterTokenFactoryAddressChange(newAddress); 160 tokenDeployer.setMasterTokenFactoryAddress(newAddress); 161 162 assertEq(tokenDeployer.masterTokenFactory(), newAddress); 163 } 164 } 165 166 contract DeployTest is CommunityTokenDeployerTest { 167 function setUp() public virtual override { 168 CommunityTokenDeployerTest.setUp(); 169 } 170 171 function test_RevertWhen_InvalidDeployerAddress() public { 172 (CommunityTokenDeployer.TokenConfig memory ownerTokenConfig, bytes memory signerPublicKey) = 173 _getOwnerTokenConfig(); 174 CommunityTokenDeployer.TokenConfig memory masterTokenConfig = _getMasterTokenConfig(); 175 CommunityTokenDeployer.DeploymentSignature memory signature = 176 _createDeploymentSignature(communityKey, communityAddress, makeAddr("someone else")); 177 vm.prank(owner); 178 vm.expectRevert(CommunityTokenDeployer.CommunityTokenDeployer_InvalidDeployerAddress.selector); 179 tokenDeployer.deploy(ownerTokenConfig, masterTokenConfig, signature, signerPublicKey); 180 } 181 182 function test_RevertWhen_InvalidDeploymentSignature() public { 183 (CommunityTokenDeployer.TokenConfig memory ownerTokenConfig, bytes memory signerPublicKey) = 184 _getOwnerTokenConfig(); 185 CommunityTokenDeployer.TokenConfig memory masterTokenConfig = _getMasterTokenConfig(); 186 CommunityTokenDeployer.DeploymentSignature memory signature = 187 _createDeploymentSignature(communityKey, makeAddr("invalid address"), owner); 188 vm.prank(owner); 189 vm.expectRevert(CommunityTokenDeployer.CommunityTokenDeployer_InvalidDeploymentSignature.selector); 190 tokenDeployer.deploy(ownerTokenConfig, masterTokenConfig, signature, signerPublicKey); 191 } 192 193 function test_RevertWhen_InvalidTokenMetadata() public { 194 (, bytes memory signerPublicKey) = _getOwnerTokenConfig(); 195 CommunityTokenDeployer.TokenConfig memory ownerTokenConfig = CommunityTokenDeployer.TokenConfig("", "", ""); 196 CommunityTokenDeployer.TokenConfig memory masterTokenConfig = CommunityTokenDeployer.TokenConfig("", "", ""); 197 CommunityTokenDeployer.DeploymentSignature memory signature = 198 _createDeploymentSignature(communityKey, communityAddress, owner); 199 200 vm.prank(owner); 201 vm.expectRevert(BaseTokenFactory.BaseTokenFactory_InvalidTokenMetadata.selector); 202 tokenDeployer.deploy(ownerTokenConfig, masterTokenConfig, signature, signerPublicKey); 203 204 // fill `masterTokenConfig` with data 205 masterTokenConfig = _getMasterTokenConfig(); 206 207 vm.prank(owner); 208 vm.expectRevert(BaseTokenFactory.BaseTokenFactory_InvalidTokenMetadata.selector); 209 tokenDeployer.deploy(ownerTokenConfig, masterTokenConfig, signature, signerPublicKey); 210 211 // fill `ownerTokenConfig` with data and reset `masterTokenConfig` 212 (ownerTokenConfig,) = _getOwnerTokenConfig(); 213 masterTokenConfig = CommunityTokenDeployer.TokenConfig("", "", ""); 214 215 vm.prank(owner); 216 vm.expectRevert(BaseTokenFactory.BaseTokenFactory_InvalidTokenMetadata.selector); 217 tokenDeployer.deploy(ownerTokenConfig, masterTokenConfig, signature, signerPublicKey); 218 } 219 220 function test_RevertWhen_InvalidSignerPublicKey() public { 221 (CommunityTokenDeployer.TokenConfig memory ownerTokenConfig,) = _getOwnerTokenConfig(); 222 CommunityTokenDeployer.TokenConfig memory masterTokenConfig = _getMasterTokenConfig(); 223 CommunityTokenDeployer.DeploymentSignature memory signature = 224 _createDeploymentSignature(communityKey, communityAddress, owner); 225 226 vm.prank(owner); 227 vm.expectRevert(CommunityTokenDeployer.CommunityTokenDeployer_InvalidSignerKeyOrCommunityAddress.selector); 228 tokenDeployer.deploy(ownerTokenConfig, masterTokenConfig, signature, bytes("")); 229 } 230 231 function test_RevertWhen_InvalidCommunityAddress() public { 232 (CommunityTokenDeployer.TokenConfig memory ownerTokenConfig, bytes memory signerPublicKey) = 233 _getOwnerTokenConfig(); 234 CommunityTokenDeployer.TokenConfig memory masterTokenConfig = _getMasterTokenConfig(); 235 CommunityTokenDeployer.DeploymentSignature memory signature = 236 _createDeploymentSignature(communityKey, address(0), owner); 237 238 vm.prank(owner); 239 vm.expectRevert(CommunityTokenDeployer.CommunityTokenDeployer_InvalidSignerKeyOrCommunityAddress.selector); 240 tokenDeployer.deploy(ownerTokenConfig, masterTokenConfig, signature, signerPublicKey); 241 } 242 243 function test_RevertWhen_AlreadyDeployed() public { 244 (CommunityTokenDeployer.TokenConfig memory ownerTokenConfig, bytes memory signerPublicKey) = 245 _getOwnerTokenConfig(); 246 CommunityTokenDeployer.TokenConfig memory masterTokenConfig = _getMasterTokenConfig(); 247 CommunityTokenDeployer.DeploymentSignature memory signature = 248 _createDeploymentSignature(communityKey, communityAddress, owner); 249 250 vm.startPrank(owner); 251 tokenDeployer.deploy(ownerTokenConfig, masterTokenConfig, signature, signerPublicKey); 252 253 vm.expectRevert(CommunityTokenDeployer.CommunityTokenDeployer_AlreadyDeployed.selector); 254 tokenDeployer.deploy(ownerTokenConfig, masterTokenConfig, signature, signerPublicKey); 255 } 256 257 function test_Deploy() public { 258 (CommunityTokenDeployer.TokenConfig memory ownerTokenConfig, bytes memory signerPublicKey) = 259 _getOwnerTokenConfig(); 260 CommunityTokenDeployer.TokenConfig memory masterTokenConfig = _getMasterTokenConfig(); 261 CommunityTokenDeployer.DeploymentSignature memory signature = 262 _createDeploymentSignature(communityKey, communityAddress, owner); 263 264 vm.prank(owner); 265 (address ownerTokenAddress, address masterTokenAddress) = 266 tokenDeployer.deploy(ownerTokenConfig, masterTokenConfig, signature, signerPublicKey); 267 268 assertEq(ownerTokenAddress, tokenRegistry.getEntry(communityAddress)); 269 assertEq(OwnerToken(ownerTokenAddress).balanceOf(owner), 1); 270 271 MasterToken masterToken = MasterToken(masterTokenAddress); 272 273 assertEq(masterToken.ownerToken(), ownerTokenAddress); 274 assertEq(masterToken.balanceOf(owner), 0); 275 assertEq(masterToken.remoteBurnable(), true); 276 assertEq(masterToken.transferable(), false); 277 } 278 }