@bannynet/core-v6 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/README.md +53 -0
  2. package/SKILLS.md +94 -0
  3. package/deployments/banny-core-v5/arbitrum/Banny721TokenUriResolver.json +1809 -0
  4. package/deployments/banny-core-v5/arbitrum_sepolia/Banny721TokenUriResolver.json +1795 -0
  5. package/deployments/banny-core-v5/base/Banny721TokenUriResolver.json +1810 -0
  6. package/deployments/banny-core-v5/base_sepolia/Banny721TokenUriResolver.json +1796 -0
  7. package/deployments/banny-core-v5/ethereum/Banny721TokenUriResolver.json +1795 -0
  8. package/deployments/banny-core-v5/optimism/Banny721TokenUriResolver.json +1810 -0
  9. package/deployments/banny-core-v5/optimism_sepolia/Banny721TokenUriResolver.json +1796 -0
  10. package/deployments/banny-core-v5/sepolia/Banny721TokenUriResolver.json +1795 -0
  11. package/foundry.toml +22 -0
  12. package/package.json +53 -0
  13. package/remappings.txt +1 -0
  14. package/script/1.Fix.s.sol +290 -0
  15. package/script/Add.Denver.s.sol +75 -0
  16. package/script/AirdropOutfits.s.sol +2302 -0
  17. package/script/Deploy.s.sol +440 -0
  18. package/script/Drop1.s.sol +979 -0
  19. package/script/MigrationContractArbitrum.sol +494 -0
  20. package/script/MigrationContractArbitrum1.sol +170 -0
  21. package/script/MigrationContractArbitrum2.sol +204 -0
  22. package/script/MigrationContractArbitrum3.sol +174 -0
  23. package/script/MigrationContractArbitrum4.sol +478 -0
  24. package/script/MigrationContractBase1.sol +444 -0
  25. package/script/MigrationContractBase2.sol +175 -0
  26. package/script/MigrationContractBase3.sol +309 -0
  27. package/script/MigrationContractBase4.sol +350 -0
  28. package/script/MigrationContractBase5.sol +259 -0
  29. package/script/MigrationContractEthereum1.sol +468 -0
  30. package/script/MigrationContractEthereum2.sol +306 -0
  31. package/script/MigrationContractEthereum3.sol +349 -0
  32. package/script/MigrationContractEthereum4.sol +352 -0
  33. package/script/MigrationContractEthereum5.sol +354 -0
  34. package/script/MigrationContractEthereum6.sol +270 -0
  35. package/script/MigrationContractEthereum7.sol +439 -0
  36. package/script/MigrationContractEthereum8.sol +385 -0
  37. package/script/MigrationContractOptimism.sol +196 -0
  38. package/script/helpers/BannyverseDeploymentLib.sol +73 -0
  39. package/script/helpers/MigrationHelper.sol +155 -0
  40. package/script/outfit_drop/generate-migration.js +3441 -0
  41. package/script/outfit_drop/raw.json +43276 -0
  42. package/slither-ci.config.json +10 -0
  43. package/sphinx.lock +521 -0
  44. package/src/Banny721TokenUriResolver.sol +1288 -0
  45. package/src/interfaces/IBanny721TokenUriResolver.sol +137 -0
  46. package/test/Banny721TokenUriResolver.t.sol +669 -0
  47. package/test/BannyAttacks.t.sol +322 -0
  48. package/test/DecorateFlow.t.sol +1056 -0
@@ -0,0 +1,204 @@
1
+ // SPDX-License-Identifier: MIT
2
+ pragma solidity 0.8.23;
3
+
4
+ import {IERC721} from "@openzeppelin/contracts/token/ERC721/IERC721.sol";
5
+ import {JB721TiersHook} from "@bananapus/721-hook-v5/src/JB721TiersHook.sol";
6
+ import {Banny721TokenUriResolver} from "../src/Banny721TokenUriResolver.sol";
7
+ import {MigrationHelper} from "./helpers/MigrationHelper.sol";
8
+
9
+ contract MigrationContractArbitrum2 {
10
+ // Define struct to hold all UPC minted tokenIds
11
+ struct MintedIds {
12
+ uint256[4] upc4;
13
+ uint256[1] upc6;
14
+ uint256[1] upc10;
15
+ uint256[1] upc11;
16
+ uint256[1] upc19;
17
+ uint256[1] upc20;
18
+ uint256[1] upc28;
19
+ uint256[1] upc31;
20
+ uint256[1] upc49;
21
+ }
22
+
23
+ address[] private transferOwners;
24
+
25
+ constructor(address[] memory _transferOwners) {
26
+ transferOwners = _transferOwners;
27
+ }
28
+
29
+ function executeMigration(
30
+ address hookAddress,
31
+ address resolverAddress,
32
+ address v4HookAddress,
33
+ address v4ResolverAddress,
34
+ address fallbackV4ResolverAddress
35
+ )
36
+ external
37
+ {
38
+ // Validate addresses
39
+ require(hookAddress != address(0), "Hook address not set");
40
+ require(resolverAddress != address(0), "Resolver address not set");
41
+ require(v4HookAddress != address(0), "V4 Hook address not set");
42
+ require(v4ResolverAddress != address(0), "V4 Resolver address not set");
43
+ require(fallbackV4ResolverAddress != address(0), "V4 fallback resolver address not set");
44
+
45
+ JB721TiersHook hook = JB721TiersHook(hookAddress);
46
+ Banny721TokenUriResolver resolver = Banny721TokenUriResolver(resolverAddress);
47
+ IERC721 v4Hook = IERC721(v4HookAddress);
48
+ Banny721TokenUriResolver v4Resolver = Banny721TokenUriResolver(v4ResolverAddress);
49
+ Banny721TokenUriResolver fallbackV4Resolver = Banny721TokenUriResolver(fallbackV4ResolverAddress);
50
+
51
+ // Arbitrum migration chunk 2/3 - 12 items
52
+
53
+ // Step 1: Assets are already minted to this contract by the deployer
54
+
55
+ // Assets are already minted to this contract by the deployer
56
+
57
+ // Create and populate the struct
58
+ // Token IDs follow formula: upc * 1000000000 + unitNumber (unitNumber starts at 1 per UPC)
59
+ MintedIds memory sortedMintedIds;
60
+
61
+ // Populate UPC 4 minted tokenIds (4 items)
62
+ sortedMintedIds.upc4[0] = 4_000_000_003; // Token ID: 4 * 1000000000 + 1
63
+ sortedMintedIds.upc4[1] = 4_000_000_004; // Token ID: 4 * 1000000000 + 2
64
+ sortedMintedIds.upc4[2] = 4_000_000_005; // Token ID: 4 * 1000000000 + 3
65
+ sortedMintedIds.upc4[3] = 4_000_000_006; // Token ID: 4 * 1000000000 + 4
66
+ // Populate UPC 6 minted tokenIds (1 items)
67
+ sortedMintedIds.upc6[0] = 6_000_000_001; // Token ID: 6 * 1000000000 + 1
68
+ // Populate UPC 10 minted tokenIds (1 items)
69
+ sortedMintedIds.upc10[0] = 10_000_000_001; // Token ID: 10 * 1000000000 + 1
70
+ // Populate UPC 11 minted tokenIds (1 items)
71
+ sortedMintedIds.upc11[0] = 11_000_000_001; // Token ID: 11 * 1000000000 + 1
72
+ // Populate UPC 19 minted tokenIds (1 items)
73
+ sortedMintedIds.upc19[0] = 19_000_000_002; // Token ID: 19 * 1000000000 + 1
74
+ // Populate UPC 20 minted tokenIds (1 items)
75
+ sortedMintedIds.upc20[0] = 20_000_000_001; // Token ID: 20 * 1000000000 + 1
76
+ // Populate UPC 28 minted tokenIds (1 items)
77
+ sortedMintedIds.upc28[0] = 28_000_000_001; // Token ID: 28 * 1000000000 + 1
78
+ // Populate UPC 31 minted tokenIds (1 items)
79
+ sortedMintedIds.upc31[0] = 31_000_000_001; // Token ID: 31 * 1000000000 + 1
80
+ // Populate UPC 49 minted tokenIds (1 items)
81
+ sortedMintedIds.upc49[0] = 49_000_000_001; // Token ID: 49 * 1000000000 + 1
82
+ // Step 1.5: Approve resolver to transfer all tokens owned by this contract
83
+ // The resolver needs approval to transfer outfits and backgrounds to itself during decoration
84
+ IERC721(address(hook)).setApprovalForAll(address(resolver), true);
85
+
86
+ // Step 2: Process each Banny body and dress them
87
+
88
+ // Dress Banny 4000000003 (Original)
89
+ {
90
+ uint256[] memory outfitIds = new uint256[](3);
91
+ outfitIds[0] = 11_000_000_001; // V4: 11000000001 -> V5: 11000000001
92
+ outfitIds[1] = 19_000_000_002; // V4: 19000000003 -> V5: 19000000002
93
+ outfitIds[2] = 28_000_000_001; // V4: 28000000001 -> V5: 28000000001
94
+
95
+ resolver.decorateBannyWith(address(hook), 4_000_000_003, 6_000_000_001, outfitIds);
96
+
97
+ MigrationHelper.verifyV4AssetMatch(
98
+ resolver, v4Resolver, fallbackV4Resolver, address(hook), v4HookAddress, 4_000_000_003
99
+ );
100
+ }
101
+
102
+ // Dress Banny 4000000004 (Original)
103
+ {
104
+ uint256[] memory outfitIds = new uint256[](2);
105
+ outfitIds[0] = 10_000_000_001; // V4: 10000000001 -> V5: 10000000001
106
+ outfitIds[1] = 20_000_000_001; // V4: 20000000001 -> V5: 20000000001
107
+
108
+ resolver.decorateBannyWith(address(hook), 4_000_000_004, 0, outfitIds);
109
+
110
+ MigrationHelper.verifyV4AssetMatch(
111
+ resolver, v4Resolver, fallbackV4Resolver, address(hook), v4HookAddress, 4_000_000_004
112
+ );
113
+ }
114
+
115
+ // Dress Banny 4000000005 (Original)
116
+ {
117
+ uint256[] memory outfitIds = new uint256[](2);
118
+ outfitIds[0] = 31_000_000_001; // V4: 31000000001 -> V5: 31000000001
119
+ outfitIds[1] = 49_000_000_001; // V4: 49000000002 -> V5: 49000000001
120
+
121
+ resolver.decorateBannyWith(address(hook), 4_000_000_005, 0, outfitIds);
122
+
123
+ MigrationHelper.verifyV4AssetMatch(
124
+ resolver, v4Resolver, fallbackV4Resolver, address(hook), v4HookAddress, 4_000_000_005
125
+ );
126
+ }
127
+
128
+ // Step 3: Transfer all assets to rightful owners using constructor data
129
+ // Generate token IDs in the same order as items appear (matching mint order)
130
+ // Token ID format: UPC * 1000000000 + unitNumber
131
+ // Note: Only banny body token IDs are guaranteed to match between V4 and V5.
132
+ // Outfits/backgrounds being worn by bannys may have different IDs, but that's OK
133
+ // since they're not transferred (only used in decorateBannyWith calls).
134
+ uint256[] memory generatedTokenIds = new uint256[](transferOwners.length);
135
+
136
+ generatedTokenIds[0] = 4_000_000_003; // Token ID (V4: 4000000003)
137
+ generatedTokenIds[1] = 4_000_000_004; // Token ID (V4: 4000000004)
138
+ generatedTokenIds[2] = 4_000_000_005; // Token ID (V4: 4000000005)
139
+ generatedTokenIds[3] = 4_000_000_006; // Token ID (V4: 4000000006)
140
+
141
+ uint256 successfulTransfers = 0;
142
+ uint256 skippedResolverOwned = 0;
143
+
144
+ for (uint256 i = 0; i < transferOwners.length; i++) {
145
+ uint256 tokenId = generatedTokenIds[i];
146
+ // Verify V4 ownership before transferring V5
147
+ address v4Owner = v4Hook.ownerOf(tokenId);
148
+ require(
149
+ v4Owner == transferOwners[i] || v4Owner == address(fallbackV4ResolverAddress),
150
+ "V4/V5 ownership mismatch for token"
151
+ );
152
+
153
+ // Skip transfer if V4 owner is the resolver (resolver holds these tokens, we shouldn't transfer to
154
+ // resolver)
155
+ if (v4Owner == address(v4ResolverAddress) || v4Owner == address(fallbackV4ResolverAddress)) {
156
+ // Token is held by resolver, skip transfer
157
+ skippedResolverOwned++;
158
+ continue;
159
+ }
160
+
161
+ IERC721(address(hook)).safeTransferFrom(address(this), transferOwners[i], tokenId);
162
+ successfulTransfers++;
163
+ }
164
+
165
+ // Verify all expected items were processed (transferred or skipped as expected)
166
+ require(successfulTransfers + skippedResolverOwned == transferOwners.length, "Not all items were processed");
167
+
168
+ // Final verification: Ensure this contract no longer owns any tokens
169
+ // This ensures all transfers completed successfully and no tokens were left behind
170
+ require(hook.balanceOf(address(this)) == 0, "Contract still owns tokens after migration");
171
+
172
+ // Verify tier balances: V5 should never exceed V4 (except for tiers owned by fallback resolver in V4)
173
+
174
+ // // Collect unique owners
175
+ // address[] memory uniqueOwners = new address[](4);
176
+
177
+ // uniqueOwners[0] = 0x08B3e694caA2F1fcF8eF71095CED1326f3454B89;
178
+ // uniqueOwners[1] = 0x9fDf876a50EA8f95017dCFC7709356887025B5BB;
179
+ // uniqueOwners[2] = 0x187089B33E5812310Ed32A57F53B3fAD0383a19D;
180
+ // uniqueOwners[3] = 0xc6404f24DB2f573F07F3A60758765caad198c0c3;
181
+
182
+ // // Collect unique tier IDs
183
+ // uint256[] memory uniqueTierIds = new uint256[](9);
184
+
185
+ // uniqueTierIds[0] = 4;
186
+ // uniqueTierIds[1] = 6;
187
+ // uniqueTierIds[2] = 10;
188
+ // uniqueTierIds[3] = 11;
189
+ // uniqueTierIds[4] = 19;
190
+ // uniqueTierIds[5] = 20;
191
+ // uniqueTierIds[6] = 28;
192
+ // uniqueTierIds[7] = 31;
193
+ // uniqueTierIds[8] = 49;
194
+
195
+ // // Verify tier balances: V5 should never exceed V4 (except for tiers owned by fallback resolver in V4)
196
+ // MigrationHelper.verifyTierBalances(
197
+ // hookAddress,
198
+ // v4HookAddress,
199
+ // fallbackV4ResolverAddress,
200
+ // uniqueOwners,
201
+ // uniqueTierIds
202
+ // );
203
+ }
204
+ }
@@ -0,0 +1,174 @@
1
+ // SPDX-License-Identifier: MIT
2
+ pragma solidity 0.8.23;
3
+
4
+ import {IERC721} from "@openzeppelin/contracts/token/ERC721/IERC721.sol";
5
+ import {JB721TiersHook} from "@bananapus/721-hook-v5/src/JB721TiersHook.sol";
6
+ import {Banny721TokenUriResolver} from "../src/Banny721TokenUriResolver.sol";
7
+ import {MigrationHelper} from "./helpers/MigrationHelper.sol";
8
+
9
+ contract MigrationContractArbitrum3 {
10
+ // Define struct to hold all UPC minted tokenIds
11
+ struct MintedIds {
12
+ uint256[3] upc4;
13
+ uint256[1] upc5;
14
+ uint256[1] upc10;
15
+ uint256[1] upc20;
16
+ uint256[1] upc28;
17
+ uint256[1] upc43;
18
+ }
19
+
20
+ address[] private transferOwners;
21
+
22
+ constructor(address[] memory _transferOwners) {
23
+ transferOwners = _transferOwners;
24
+ }
25
+
26
+ function executeMigration(
27
+ address hookAddress,
28
+ address resolverAddress,
29
+ address v4HookAddress,
30
+ address v4ResolverAddress,
31
+ address fallbackV4ResolverAddress
32
+ )
33
+ external
34
+ {
35
+ // Validate addresses
36
+ require(hookAddress != address(0), "Hook address not set");
37
+ require(resolverAddress != address(0), "Resolver address not set");
38
+ require(v4HookAddress != address(0), "V4 Hook address not set");
39
+ require(v4ResolverAddress != address(0), "V4 Resolver address not set");
40
+ require(fallbackV4ResolverAddress != address(0), "V4 fallback resolver address not set");
41
+
42
+ JB721TiersHook hook = JB721TiersHook(hookAddress);
43
+ Banny721TokenUriResolver resolver = Banny721TokenUriResolver(resolverAddress);
44
+ IERC721 v4Hook = IERC721(v4HookAddress);
45
+ Banny721TokenUriResolver v4Resolver = Banny721TokenUriResolver(v4ResolverAddress);
46
+ Banny721TokenUriResolver fallbackV4Resolver = Banny721TokenUriResolver(fallbackV4ResolverAddress);
47
+
48
+ // Arbitrum migration chunk 3/3 - 8 items
49
+
50
+ // Step 1: Assets are already minted to this contract by the deployer
51
+
52
+ // Assets are already minted to this contract by the deployer
53
+
54
+ // Create and populate the struct
55
+ // Token IDs follow formula: upc * 1000000000 + unitNumber (unitNumber starts at 1 per UPC)
56
+ MintedIds memory sortedMintedIds;
57
+
58
+ // Populate UPC 4 minted tokenIds (3 items)
59
+ sortedMintedIds.upc4[0] = 4_000_000_007; // Token ID: 4 * 1000000000 + 1
60
+ sortedMintedIds.upc4[1] = 4_000_000_008; // Token ID: 4 * 1000000000 + 2
61
+ sortedMintedIds.upc4[2] = 4_000_000_009; // Token ID: 4 * 1000000000 + 3
62
+ // Populate UPC 5 minted tokenIds (1 items)
63
+ sortedMintedIds.upc5[0] = 5_000_000_002; // Token ID: 5 * 1000000000 + 1
64
+ // Populate UPC 10 minted tokenIds (1 items)
65
+ sortedMintedIds.upc10[0] = 10_000_000_002; // Token ID: 10 * 1000000000 + 1
66
+ // Populate UPC 20 minted tokenIds (1 items)
67
+ sortedMintedIds.upc20[0] = 20_000_000_002; // Token ID: 20 * 1000000000 + 1
68
+ // Populate UPC 28 minted tokenIds (1 items)
69
+ sortedMintedIds.upc28[0] = 28_000_000_002; // Token ID: 28 * 1000000000 + 1
70
+ // Populate UPC 43 minted tokenIds (1 items)
71
+ sortedMintedIds.upc43[0] = 43_000_000_001; // Token ID: 43 * 1000000000 + 1
72
+ // Step 1.5: Approve resolver to transfer all tokens owned by this contract
73
+ // The resolver needs approval to transfer outfits and backgrounds to itself during decoration
74
+ IERC721(address(hook)).setApprovalForAll(address(resolver), true);
75
+
76
+ // Step 2: Process each Banny body and dress them
77
+
78
+ // Dress Banny 4000000007 (Original)
79
+ {
80
+ uint256[] memory outfitIds = new uint256[](3);
81
+ outfitIds[0] = 10_000_000_002; // V4: 10000000002 -> V5: 10000000002
82
+ outfitIds[1] = 20_000_000_002; // V4: 20000000002 -> V5: 20000000002
83
+ outfitIds[2] = 43_000_000_001; // V4: 43000000001 -> V5: 43000000001
84
+
85
+ resolver.decorateBannyWith(address(hook), 4_000_000_007, 5_000_000_002, outfitIds);
86
+
87
+ MigrationHelper.verifyV4AssetMatch(
88
+ resolver, v4Resolver, fallbackV4Resolver, address(hook), v4HookAddress, 4_000_000_007
89
+ );
90
+ }
91
+
92
+ // Dress Banny 4000000009 (Original)
93
+ {
94
+ uint256[] memory outfitIds = new uint256[](1);
95
+ outfitIds[0] = 28_000_000_002; // V4: 28000000002 -> V5: 28000000002
96
+
97
+ resolver.decorateBannyWith(address(hook), 4_000_000_009, 0, outfitIds);
98
+
99
+ MigrationHelper.verifyV4AssetMatch(
100
+ resolver, v4Resolver, fallbackV4Resolver, address(hook), v4HookAddress, 4_000_000_009
101
+ );
102
+ }
103
+
104
+ // Step 3: Transfer all assets to rightful owners using constructor data
105
+ // Generate token IDs in the same order as items appear (matching mint order)
106
+ // Token ID format: UPC * 1000000000 + unitNumber
107
+ // Note: Only banny body token IDs are guaranteed to match between V4 and V5.
108
+ // Outfits/backgrounds being worn by bannys may have different IDs, but that's OK
109
+ // since they're not transferred (only used in decorateBannyWith calls).
110
+ uint256[] memory generatedTokenIds = new uint256[](transferOwners.length);
111
+
112
+ generatedTokenIds[0] = 4_000_000_007; // Token ID (V4: 4000000007)
113
+ generatedTokenIds[1] = 4_000_000_008; // Token ID (V4: 4000000008)
114
+ generatedTokenIds[2] = 4_000_000_009; // Token ID (V4: 4000000009)
115
+
116
+ uint256 successfulTransfers = 0;
117
+ uint256 skippedResolverOwned = 0;
118
+
119
+ for (uint256 i = 0; i < transferOwners.length; i++) {
120
+ uint256 tokenId = generatedTokenIds[i];
121
+ // Verify V4 ownership before transferring V5
122
+ address v4Owner = v4Hook.ownerOf(tokenId);
123
+ require(
124
+ v4Owner == transferOwners[i] || v4Owner == address(fallbackV4ResolverAddress),
125
+ "V4/V5 ownership mismatch for token"
126
+ );
127
+
128
+ // Skip transfer if V4 owner is the resolver (resolver holds these tokens, we shouldn't transfer to
129
+ // resolver)
130
+ if (v4Owner == address(v4ResolverAddress) || v4Owner == address(fallbackV4ResolverAddress)) {
131
+ // Token is held by resolver, skip transfer
132
+ skippedResolverOwned++;
133
+ continue;
134
+ }
135
+
136
+ IERC721(address(hook)).safeTransferFrom(address(this), transferOwners[i], tokenId);
137
+ successfulTransfers++;
138
+ }
139
+
140
+ // Verify all expected items were processed (transferred or skipped as expected)
141
+ require(successfulTransfers + skippedResolverOwned == transferOwners.length, "Not all items were processed");
142
+
143
+ // Final verification: Ensure this contract no longer owns any tokens
144
+ // This ensures all transfers completed successfully and no tokens were left behind
145
+ require(hook.balanceOf(address(this)) == 0, "Contract still owns tokens after migration");
146
+
147
+ // Verify tier balances: V5 should never exceed V4 (except for tiers owned by fallback resolver in V4)
148
+
149
+ // // Collect unique owners
150
+ // address[] memory uniqueOwners = new address[](2);
151
+
152
+ // uniqueOwners[0] = 0xB2d3900807094D4Fe47405871B0C8AdB58E10D42;
153
+ // uniqueOwners[1] = 0x57a482EA32c7F75A9C0734206f5BD4f9BCb38e12;
154
+
155
+ // // Collect unique tier IDs
156
+ // uint256[] memory uniqueTierIds = new uint256[](6);
157
+
158
+ // uniqueTierIds[0] = 4;
159
+ // uniqueTierIds[1] = 5;
160
+ // uniqueTierIds[2] = 10;
161
+ // uniqueTierIds[3] = 20;
162
+ // uniqueTierIds[4] = 28;
163
+ // uniqueTierIds[5] = 43;
164
+
165
+ // // Verify tier balances: V5 should never exceed V4 (except for tiers owned by fallback resolver in V4)
166
+ // MigrationHelper.verifyTierBalances(
167
+ // hookAddress,
168
+ // v4HookAddress,
169
+ // fallbackV4ResolverAddress,
170
+ // uniqueOwners,
171
+ // uniqueTierIds
172
+ // );
173
+ }
174
+ }