@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,385 @@
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
+ /// @notice Migration contract for Ethereum to handle standalone outfits and backgrounds
10
+ /// that are not worn/used by any banny. These assets are minted to this contract
11
+ /// and then transferred directly to their owners.
12
+ contract MigrationContractEthereum8 {
13
+ address[] private transferOwners;
14
+
15
+ constructor(address[] memory _transferOwners) {
16
+ transferOwners = _transferOwners;
17
+ }
18
+
19
+ function executeMigration(
20
+ address hookAddress,
21
+ address resolverAddress,
22
+ address v4HookAddress,
23
+ address v4ResolverAddress,
24
+ address fallbackV4ResolverAddress
25
+ )
26
+ external
27
+ {
28
+ // Validate addresses
29
+ require(hookAddress != address(0), "Hook address not set");
30
+ require(resolverAddress != address(0), "Resolver address not set");
31
+ require(v4HookAddress != address(0), "V4 Hook address not set");
32
+ require(v4ResolverAddress != address(0), "V4 Resolver address not set");
33
+ require(fallbackV4ResolverAddress != address(0), "V4 fallback resolver address not set");
34
+
35
+ JB721TiersHook hook = JB721TiersHook(hookAddress);
36
+ IERC721 v4Hook = IERC721(v4HookAddress);
37
+
38
+ // Ethereum migration - Standalone outfits and backgrounds (140 items)
39
+ // These are assets that are NOT being worn/used by any banny
40
+
41
+ // Assets are already minted to this contract by the deployer
42
+ // V5 token IDs are calculated based on mint order (continuing from previous chunks)
43
+ // V4 token IDs are the original token IDs from V4
44
+
45
+ // Generate token IDs - store both V5 minted token IDs and original V4 token IDs
46
+ uint256[] memory v5TokenIds = new uint256[](transferOwners.length);
47
+ uint256[] memory v4TokenIds = new uint256[](transferOwners.length);
48
+ v5TokenIds[0] = 49_000_000_006; // Minted V5 Token ID
49
+ v4TokenIds[0] = 49_000_000_006; // Original V4 Token ID
50
+ v5TokenIds[1] = 49_000_000_007; // Minted V5 Token ID
51
+ v4TokenIds[1] = 49_000_000_007; // Original V4 Token ID
52
+ v5TokenIds[2] = 49_000_000_008; // Minted V5 Token ID
53
+ v4TokenIds[2] = 49_000_000_008; // Original V4 Token ID
54
+ v5TokenIds[3] = 49_000_000_009; // Minted V5 Token ID
55
+ v4TokenIds[3] = 49_000_000_009; // Original V4 Token ID
56
+ v5TokenIds[4] = 49_000_000_010; // Minted V5 Token ID
57
+ v4TokenIds[4] = 49_000_000_010; // Original V4 Token ID
58
+ v5TokenIds[5] = 49_000_000_011; // Minted V5 Token ID
59
+ v4TokenIds[5] = 49_000_000_011; // Original V4 Token ID
60
+ v5TokenIds[6] = 49_000_000_012; // Minted V5 Token ID
61
+ v4TokenIds[6] = 49_000_000_012; // Original V4 Token ID
62
+ v5TokenIds[7] = 49_000_000_013; // Minted V5 Token ID
63
+ v4TokenIds[7] = 49_000_000_013; // Original V4 Token ID
64
+ v5TokenIds[8] = 49_000_000_014; // Minted V5 Token ID
65
+ v4TokenIds[8] = 49_000_000_014; // Original V4 Token ID
66
+ v5TokenIds[9] = 49_000_000_015; // Minted V5 Token ID
67
+ v4TokenIds[9] = 49_000_000_015; // Original V4 Token ID
68
+ v5TokenIds[10] = 49_000_000_016; // Minted V5 Token ID
69
+ v4TokenIds[10] = 49_000_000_016; // Original V4 Token ID
70
+ v5TokenIds[11] = 49_000_000_017; // Minted V5 Token ID
71
+ v4TokenIds[11] = 49_000_000_017; // Original V4 Token ID
72
+ v5TokenIds[12] = 49_000_000_018; // Minted V5 Token ID
73
+ v4TokenIds[12] = 49_000_000_018; // Original V4 Token ID
74
+ v5TokenIds[13] = 49_000_000_019; // Minted V5 Token ID
75
+ v4TokenIds[13] = 49_000_000_019; // Original V4 Token ID
76
+ v5TokenIds[14] = 49_000_000_020; // Minted V5 Token ID
77
+ v4TokenIds[14] = 49_000_000_020; // Original V4 Token ID
78
+ v5TokenIds[15] = 49_000_000_021; // Minted V5 Token ID
79
+ v4TokenIds[15] = 49_000_000_021; // Original V4 Token ID
80
+ v5TokenIds[16] = 49_000_000_022; // Minted V5 Token ID
81
+ v4TokenIds[16] = 49_000_000_022; // Original V4 Token ID
82
+ v5TokenIds[17] = 49_000_000_023; // Minted V5 Token ID
83
+ v4TokenIds[17] = 49_000_000_023; // Original V4 Token ID
84
+ v5TokenIds[18] = 49_000_000_024; // Minted V5 Token ID
85
+ v4TokenIds[18] = 49_000_000_024; // Original V4 Token ID
86
+ v5TokenIds[19] = 49_000_000_025; // Minted V5 Token ID
87
+ v4TokenIds[19] = 49_000_000_025; // Original V4 Token ID
88
+ v5TokenIds[20] = 49_000_000_026; // Minted V5 Token ID
89
+ v4TokenIds[20] = 49_000_000_026; // Original V4 Token ID
90
+ v5TokenIds[21] = 49_000_000_027; // Minted V5 Token ID
91
+ v4TokenIds[21] = 49_000_000_027; // Original V4 Token ID
92
+ v5TokenIds[22] = 49_000_000_028; // Minted V5 Token ID
93
+ v4TokenIds[22] = 49_000_000_028; // Original V4 Token ID
94
+ v5TokenIds[23] = 49_000_000_029; // Minted V5 Token ID
95
+ v4TokenIds[23] = 49_000_000_029; // Original V4 Token ID
96
+ v5TokenIds[24] = 49_000_000_030; // Minted V5 Token ID
97
+ v4TokenIds[24] = 49_000_000_030; // Original V4 Token ID
98
+ v5TokenIds[25] = 49_000_000_031; // Minted V5 Token ID
99
+ v4TokenIds[25] = 49_000_000_031; // Original V4 Token ID
100
+ v5TokenIds[26] = 49_000_000_032; // Minted V5 Token ID
101
+ v4TokenIds[26] = 49_000_000_032; // Original V4 Token ID
102
+ v5TokenIds[27] = 49_000_000_033; // Minted V5 Token ID
103
+ v4TokenIds[27] = 49_000_000_033; // Original V4 Token ID
104
+ v5TokenIds[28] = 49_000_000_034; // Minted V5 Token ID
105
+ v4TokenIds[28] = 49_000_000_034; // Original V4 Token ID
106
+ v5TokenIds[29] = 49_000_000_035; // Minted V5 Token ID
107
+ v4TokenIds[29] = 49_000_000_035; // Original V4 Token ID
108
+ v5TokenIds[30] = 49_000_000_036; // Minted V5 Token ID
109
+ v4TokenIds[30] = 49_000_000_036; // Original V4 Token ID
110
+ v5TokenIds[31] = 49_000_000_037; // Minted V5 Token ID
111
+ v4TokenIds[31] = 49_000_000_037; // Original V4 Token ID
112
+ v5TokenIds[32] = 49_000_000_038; // Minted V5 Token ID
113
+ v4TokenIds[32] = 49_000_000_038; // Original V4 Token ID
114
+ v5TokenIds[33] = 49_000_000_039; // Minted V5 Token ID
115
+ v4TokenIds[33] = 49_000_000_039; // Original V4 Token ID
116
+ v5TokenIds[34] = 49_000_000_040; // Minted V5 Token ID
117
+ v4TokenIds[34] = 49_000_000_040; // Original V4 Token ID
118
+ v5TokenIds[35] = 49_000_000_041; // Minted V5 Token ID
119
+ v4TokenIds[35] = 49_000_000_041; // Original V4 Token ID
120
+ v5TokenIds[36] = 49_000_000_042; // Minted V5 Token ID
121
+ v4TokenIds[36] = 49_000_000_042; // Original V4 Token ID
122
+ v5TokenIds[37] = 49_000_000_043; // Minted V5 Token ID
123
+ v4TokenIds[37] = 49_000_000_043; // Original V4 Token ID
124
+ v5TokenIds[38] = 49_000_000_044; // Minted V5 Token ID
125
+ v4TokenIds[38] = 49_000_000_044; // Original V4 Token ID
126
+ v5TokenIds[39] = 49_000_000_045; // Minted V5 Token ID
127
+ v4TokenIds[39] = 49_000_000_045; // Original V4 Token ID
128
+ v5TokenIds[40] = 49_000_000_046; // Minted V5 Token ID
129
+ v4TokenIds[40] = 49_000_000_046; // Original V4 Token ID
130
+ v5TokenIds[41] = 49_000_000_047; // Minted V5 Token ID
131
+ v4TokenIds[41] = 49_000_000_047; // Original V4 Token ID
132
+ v5TokenIds[42] = 49_000_000_048; // Minted V5 Token ID
133
+ v4TokenIds[42] = 49_000_000_048; // Original V4 Token ID
134
+ v5TokenIds[43] = 49_000_000_049; // Minted V5 Token ID
135
+ v4TokenIds[43] = 49_000_000_049; // Original V4 Token ID
136
+ v5TokenIds[44] = 49_000_000_050; // Minted V5 Token ID
137
+ v4TokenIds[44] = 49_000_000_050; // Original V4 Token ID
138
+ v5TokenIds[45] = 49_000_000_051; // Minted V5 Token ID
139
+ v4TokenIds[45] = 49_000_000_051; // Original V4 Token ID
140
+ v5TokenIds[46] = 49_000_000_052; // Minted V5 Token ID
141
+ v4TokenIds[46] = 49_000_000_052; // Original V4 Token ID
142
+ v5TokenIds[47] = 49_000_000_053; // Minted V5 Token ID
143
+ v4TokenIds[47] = 49_000_000_053; // Original V4 Token ID
144
+ v5TokenIds[48] = 49_000_000_054; // Minted V5 Token ID
145
+ v4TokenIds[48] = 49_000_000_054; // Original V4 Token ID
146
+ v5TokenIds[49] = 49_000_000_055; // Minted V5 Token ID
147
+ v4TokenIds[49] = 49_000_000_055; // Original V4 Token ID
148
+ v5TokenIds[50] = 49_000_000_056; // Minted V5 Token ID
149
+ v4TokenIds[50] = 49_000_000_056; // Original V4 Token ID
150
+ v5TokenIds[51] = 49_000_000_057; // Minted V5 Token ID
151
+ v4TokenIds[51] = 49_000_000_057; // Original V4 Token ID
152
+ v5TokenIds[52] = 49_000_000_058; // Minted V5 Token ID
153
+ v4TokenIds[52] = 49_000_000_058; // Original V4 Token ID
154
+ v5TokenIds[53] = 49_000_000_059; // Minted V5 Token ID
155
+ v4TokenIds[53] = 49_000_000_059; // Original V4 Token ID
156
+ v5TokenIds[54] = 49_000_000_060; // Minted V5 Token ID
157
+ v4TokenIds[54] = 49_000_000_060; // Original V4 Token ID
158
+ v5TokenIds[55] = 49_000_000_061; // Minted V5 Token ID
159
+ v4TokenIds[55] = 49_000_000_061; // Original V4 Token ID
160
+ v5TokenIds[56] = 49_000_000_062; // Minted V5 Token ID
161
+ v4TokenIds[56] = 49_000_000_062; // Original V4 Token ID
162
+ v5TokenIds[57] = 49_000_000_063; // Minted V5 Token ID
163
+ v4TokenIds[57] = 49_000_000_063; // Original V4 Token ID
164
+ v5TokenIds[58] = 49_000_000_064; // Minted V5 Token ID
165
+ v4TokenIds[58] = 49_000_000_064; // Original V4 Token ID
166
+ v5TokenIds[59] = 49_000_000_065; // Minted V5 Token ID
167
+ v4TokenIds[59] = 49_000_000_065; // Original V4 Token ID
168
+ v5TokenIds[60] = 49_000_000_066; // Minted V5 Token ID
169
+ v4TokenIds[60] = 49_000_000_066; // Original V4 Token ID
170
+ v5TokenIds[61] = 49_000_000_067; // Minted V5 Token ID
171
+ v4TokenIds[61] = 49_000_000_067; // Original V4 Token ID
172
+ v5TokenIds[62] = 49_000_000_068; // Minted V5 Token ID
173
+ v4TokenIds[62] = 49_000_000_068; // Original V4 Token ID
174
+ v5TokenIds[63] = 49_000_000_069; // Minted V5 Token ID
175
+ v4TokenIds[63] = 49_000_000_069; // Original V4 Token ID
176
+ v5TokenIds[64] = 49_000_000_070; // Minted V5 Token ID
177
+ v4TokenIds[64] = 49_000_000_070; // Original V4 Token ID
178
+ v5TokenIds[65] = 49_000_000_071; // Minted V5 Token ID
179
+ v4TokenIds[65] = 49_000_000_071; // Original V4 Token ID
180
+ v5TokenIds[66] = 49_000_000_072; // Minted V5 Token ID
181
+ v4TokenIds[66] = 49_000_000_072; // Original V4 Token ID
182
+ v5TokenIds[67] = 49_000_000_073; // Minted V5 Token ID
183
+ v4TokenIds[67] = 49_000_000_073; // Original V4 Token ID
184
+ v5TokenIds[68] = 49_000_000_074; // Minted V5 Token ID
185
+ v4TokenIds[68] = 49_000_000_074; // Original V4 Token ID
186
+ v5TokenIds[69] = 49_000_000_075; // Minted V5 Token ID
187
+ v4TokenIds[69] = 49_000_000_075; // Original V4 Token ID
188
+ v5TokenIds[70] = 49_000_000_076; // Minted V5 Token ID
189
+ v4TokenIds[70] = 49_000_000_076; // Original V4 Token ID
190
+ v5TokenIds[71] = 49_000_000_077; // Minted V5 Token ID
191
+ v4TokenIds[71] = 49_000_000_077; // Original V4 Token ID
192
+ v5TokenIds[72] = 49_000_000_078; // Minted V5 Token ID
193
+ v4TokenIds[72] = 49_000_000_078; // Original V4 Token ID
194
+ v5TokenIds[73] = 49_000_000_079; // Minted V5 Token ID
195
+ v4TokenIds[73] = 49_000_000_079; // Original V4 Token ID
196
+ v5TokenIds[74] = 49_000_000_080; // Minted V5 Token ID
197
+ v4TokenIds[74] = 49_000_000_080; // Original V4 Token ID
198
+ v5TokenIds[75] = 49_000_000_081; // Minted V5 Token ID
199
+ v4TokenIds[75] = 49_000_000_081; // Original V4 Token ID
200
+ v5TokenIds[76] = 49_000_000_082; // Minted V5 Token ID
201
+ v4TokenIds[76] = 49_000_000_082; // Original V4 Token ID
202
+ v5TokenIds[77] = 49_000_000_083; // Minted V5 Token ID
203
+ v4TokenIds[77] = 49_000_000_083; // Original V4 Token ID
204
+ v5TokenIds[78] = 49_000_000_084; // Minted V5 Token ID
205
+ v4TokenIds[78] = 49_000_000_084; // Original V4 Token ID
206
+ v5TokenIds[79] = 49_000_000_085; // Minted V5 Token ID
207
+ v4TokenIds[79] = 49_000_000_085; // Original V4 Token ID
208
+ v5TokenIds[80] = 49_000_000_086; // Minted V5 Token ID
209
+ v4TokenIds[80] = 49_000_000_086; // Original V4 Token ID
210
+ v5TokenIds[81] = 49_000_000_087; // Minted V5 Token ID
211
+ v4TokenIds[81] = 49_000_000_087; // Original V4 Token ID
212
+ v5TokenIds[82] = 49_000_000_088; // Minted V5 Token ID
213
+ v4TokenIds[82] = 49_000_000_088; // Original V4 Token ID
214
+ v5TokenIds[83] = 49_000_000_089; // Minted V5 Token ID
215
+ v4TokenIds[83] = 49_000_000_089; // Original V4 Token ID
216
+ v5TokenIds[84] = 49_000_000_090; // Minted V5 Token ID
217
+ v4TokenIds[84] = 49_000_000_090; // Original V4 Token ID
218
+ v5TokenIds[85] = 49_000_000_091; // Minted V5 Token ID
219
+ v4TokenIds[85] = 49_000_000_091; // Original V4 Token ID
220
+ v5TokenIds[86] = 49_000_000_092; // Minted V5 Token ID
221
+ v4TokenIds[86] = 49_000_000_092; // Original V4 Token ID
222
+ v5TokenIds[87] = 49_000_000_093; // Minted V5 Token ID
223
+ v4TokenIds[87] = 49_000_000_093; // Original V4 Token ID
224
+ v5TokenIds[88] = 49_000_000_094; // Minted V5 Token ID
225
+ v4TokenIds[88] = 49_000_000_094; // Original V4 Token ID
226
+ v5TokenIds[89] = 49_000_000_095; // Minted V5 Token ID
227
+ v4TokenIds[89] = 49_000_000_095; // Original V4 Token ID
228
+ v5TokenIds[90] = 49_000_000_096; // Minted V5 Token ID
229
+ v4TokenIds[90] = 49_000_000_096; // Original V4 Token ID
230
+ v5TokenIds[91] = 49_000_000_097; // Minted V5 Token ID
231
+ v4TokenIds[91] = 49_000_000_097; // Original V4 Token ID
232
+ v5TokenIds[92] = 49_000_000_098; // Minted V5 Token ID
233
+ v4TokenIds[92] = 49_000_000_098; // Original V4 Token ID
234
+ v5TokenIds[93] = 49_000_000_099; // Minted V5 Token ID
235
+ v4TokenIds[93] = 49_000_000_099; // Original V4 Token ID
236
+ v5TokenIds[94] = 49_000_000_100; // Minted V5 Token ID
237
+ v4TokenIds[94] = 49_000_000_100; // Original V4 Token ID
238
+ v5TokenIds[95] = 49_000_000_101; // Minted V5 Token ID
239
+ v4TokenIds[95] = 49_000_000_101; // Original V4 Token ID
240
+ v5TokenIds[96] = 49_000_000_102; // Minted V5 Token ID
241
+ v4TokenIds[96] = 49_000_000_102; // Original V4 Token ID
242
+ v5TokenIds[97] = 49_000_000_103; // Minted V5 Token ID
243
+ v4TokenIds[97] = 49_000_000_103; // Original V4 Token ID
244
+ v5TokenIds[98] = 49_000_000_104; // Minted V5 Token ID
245
+ v4TokenIds[98] = 49_000_000_104; // Original V4 Token ID
246
+ v5TokenIds[99] = 49_000_000_105; // Minted V5 Token ID
247
+ v4TokenIds[99] = 49_000_000_105; // Original V4 Token ID
248
+ v5TokenIds[100] = 49_000_000_106; // Minted V5 Token ID
249
+ v4TokenIds[100] = 49_000_000_106; // Original V4 Token ID
250
+ v5TokenIds[101] = 49_000_000_107; // Minted V5 Token ID
251
+ v4TokenIds[101] = 49_000_000_107; // Original V4 Token ID
252
+ v5TokenIds[102] = 49_000_000_108; // Minted V5 Token ID
253
+ v4TokenIds[102] = 49_000_000_108; // Original V4 Token ID
254
+ v5TokenIds[103] = 49_000_000_109; // Minted V5 Token ID
255
+ v4TokenIds[103] = 49_000_000_109; // Original V4 Token ID
256
+ v5TokenIds[104] = 49_000_000_110; // Minted V5 Token ID
257
+ v4TokenIds[104] = 49_000_000_110; // Original V4 Token ID
258
+ v5TokenIds[105] = 49_000_000_111; // Minted V5 Token ID
259
+ v4TokenIds[105] = 49_000_000_111; // Original V4 Token ID
260
+ v5TokenIds[106] = 49_000_000_112; // Minted V5 Token ID
261
+ v4TokenIds[106] = 49_000_000_112; // Original V4 Token ID
262
+ v5TokenIds[107] = 49_000_000_113; // Minted V5 Token ID
263
+ v4TokenIds[107] = 49_000_000_113; // Original V4 Token ID
264
+ v5TokenIds[108] = 49_000_000_114; // Minted V5 Token ID
265
+ v4TokenIds[108] = 49_000_000_114; // Original V4 Token ID
266
+ v5TokenIds[109] = 49_000_000_115; // Minted V5 Token ID
267
+ v4TokenIds[109] = 49_000_000_115; // Original V4 Token ID
268
+ v5TokenIds[110] = 49_000_000_116; // Minted V5 Token ID
269
+ v4TokenIds[110] = 49_000_000_116; // Original V4 Token ID
270
+ v5TokenIds[111] = 49_000_000_117; // Minted V5 Token ID
271
+ v4TokenIds[111] = 49_000_000_117; // Original V4 Token ID
272
+ v5TokenIds[112] = 49_000_000_118; // Minted V5 Token ID
273
+ v4TokenIds[112] = 49_000_000_118; // Original V4 Token ID
274
+ v5TokenIds[113] = 49_000_000_119; // Minted V5 Token ID
275
+ v4TokenIds[113] = 49_000_000_119; // Original V4 Token ID
276
+ v5TokenIds[114] = 49_000_000_120; // Minted V5 Token ID
277
+ v4TokenIds[114] = 49_000_000_120; // Original V4 Token ID
278
+ v5TokenIds[115] = 49_000_000_121; // Minted V5 Token ID
279
+ v4TokenIds[115] = 49_000_000_121; // Original V4 Token ID
280
+ v5TokenIds[116] = 49_000_000_122; // Minted V5 Token ID
281
+ v4TokenIds[116] = 49_000_000_122; // Original V4 Token ID
282
+ v5TokenIds[117] = 49_000_000_123; // Minted V5 Token ID
283
+ v4TokenIds[117] = 49_000_000_123; // Original V4 Token ID
284
+ v5TokenIds[118] = 49_000_000_124; // Minted V5 Token ID
285
+ v4TokenIds[118] = 49_000_000_124; // Original V4 Token ID
286
+ v5TokenIds[119] = 49_000_000_125; // Minted V5 Token ID
287
+ v4TokenIds[119] = 49_000_000_125; // Original V4 Token ID
288
+ v5TokenIds[120] = 49_000_000_126; // Minted V5 Token ID
289
+ v4TokenIds[120] = 49_000_000_126; // Original V4 Token ID
290
+ v5TokenIds[121] = 49_000_000_127; // Minted V5 Token ID
291
+ v4TokenIds[121] = 49_000_000_127; // Original V4 Token ID
292
+ v5TokenIds[122] = 49_000_000_128; // Minted V5 Token ID
293
+ v4TokenIds[122] = 49_000_000_128; // Original V4 Token ID
294
+ v5TokenIds[123] = 49_000_000_129; // Minted V5 Token ID
295
+ v4TokenIds[123] = 49_000_000_129; // Original V4 Token ID
296
+ v5TokenIds[124] = 49_000_000_130; // Minted V5 Token ID
297
+ v4TokenIds[124] = 49_000_000_130; // Original V4 Token ID
298
+ v5TokenIds[125] = 49_000_000_131; // Minted V5 Token ID
299
+ v4TokenIds[125] = 49_000_000_131; // Original V4 Token ID
300
+ v5TokenIds[126] = 49_000_000_132; // Minted V5 Token ID
301
+ v4TokenIds[126] = 49_000_000_132; // Original V4 Token ID
302
+ v5TokenIds[127] = 49_000_000_133; // Minted V5 Token ID
303
+ v4TokenIds[127] = 49_000_000_133; // Original V4 Token ID
304
+ v5TokenIds[128] = 49_000_000_134; // Minted V5 Token ID
305
+ v4TokenIds[128] = 49_000_000_134; // Original V4 Token ID
306
+ v5TokenIds[129] = 49_000_000_135; // Minted V5 Token ID
307
+ v4TokenIds[129] = 49_000_000_135; // Original V4 Token ID
308
+ v5TokenIds[130] = 49_000_000_136; // Minted V5 Token ID
309
+ v4TokenIds[130] = 49_000_000_136; // Original V4 Token ID
310
+ v5TokenIds[131] = 49_000_000_137; // Minted V5 Token ID
311
+ v4TokenIds[131] = 49_000_000_137; // Original V4 Token ID
312
+ v5TokenIds[132] = 49_000_000_138; // Minted V5 Token ID
313
+ v4TokenIds[132] = 49_000_000_138; // Original V4 Token ID
314
+ v5TokenIds[133] = 49_000_000_139; // Minted V5 Token ID
315
+ v4TokenIds[133] = 49_000_000_139; // Original V4 Token ID
316
+ v5TokenIds[134] = 49_000_000_140; // Minted V5 Token ID
317
+ v4TokenIds[134] = 49_000_000_140; // Original V4 Token ID
318
+ v5TokenIds[135] = 49_000_000_141; // Minted V5 Token ID
319
+ v4TokenIds[135] = 49_000_000_141; // Original V4 Token ID
320
+ v5TokenIds[136] = 49_000_000_142; // Minted V5 Token ID
321
+ v4TokenIds[136] = 49_000_000_142; // Original V4 Token ID
322
+ v5TokenIds[137] = 49_000_000_143; // Minted V5 Token ID
323
+ v4TokenIds[137] = 49_000_000_143; // Original V4 Token ID
324
+ v5TokenIds[138] = 49_000_000_144; // Minted V5 Token ID
325
+ v4TokenIds[138] = 49_000_000_144; // Original V4 Token ID
326
+ v5TokenIds[139] = 49_000_000_145; // Minted V5 Token ID
327
+ v4TokenIds[139] = 49_000_000_145; // Original V4 Token ID
328
+
329
+ uint256 successfulTransfers = 0;
330
+
331
+ for (uint256 i = 0; i < transferOwners.length; i++) {
332
+ uint256 v5TokenId = v5TokenIds[i];
333
+ uint256 v4TokenId = v4TokenIds[i];
334
+
335
+ // Verify V4 ownership using the original V4 token ID
336
+ address v4Owner = v4Hook.ownerOf(v4TokenId);
337
+ address expectedOwner = transferOwners[i];
338
+
339
+ require(
340
+ v4Owner != address(v4ResolverAddress),
341
+ "Token owned by main resolver in V4 - should not be in unused assets contract"
342
+ );
343
+
344
+ if (v4Owner == address(fallbackV4ResolverAddress)) {
345
+ require(
346
+ expectedOwner != address(v4ResolverAddress) && expectedOwner != address(fallbackV4ResolverAddress),
347
+ "Token owned by fallback resolver in V4 but expected owner is also a resolver - should not be in unused assets contract"
348
+ );
349
+ } else {
350
+ require(v4Owner == expectedOwner, "V4/V5 ownership mismatch for token");
351
+ }
352
+
353
+ require(hook.ownerOf(v5TokenId) == address(this), "Contract does not own token");
354
+
355
+ IERC721(address(hook)).safeTransferFrom(address(this), transferOwners[i], v5TokenId);
356
+ successfulTransfers++;
357
+ }
358
+
359
+ require(successfulTransfers == transferOwners.length, "Not all items were transferred");
360
+
361
+ require(hook.balanceOf(address(this)) == 0, "Contract still owns tokens after migration");
362
+
363
+ // Verify tier balances: V5 should never exceed V4 (except for tiers owned by fallback resolver in V4)
364
+
365
+ // // Collect unique owners
366
+ // address[] memory uniqueOwners = new address[](2);
367
+
368
+ // uniqueOwners[0] = 0x7C3F14075F6477fea1aF6cf59f325afDfcD3Ddf7;
369
+ // uniqueOwners[1] = 0x823b92d6a4b2AED4b15675c7917c9f922ea8ADAD;
370
+
371
+ // // Collect unique tier IDs
372
+ // uint256[] memory uniqueTierIds = new uint256[](1);
373
+
374
+ // uniqueTierIds[0] = 49;
375
+
376
+ // // Verify tier balances: V5 should never exceed V4 (except for tiers owned by fallback resolver in V4)
377
+ // MigrationHelper.verifyTierBalances(
378
+ // hookAddress,
379
+ // v4HookAddress,
380
+ // fallbackV4ResolverAddress,
381
+ // uniqueOwners,
382
+ // uniqueTierIds
383
+ // );
384
+ }
385
+ }
@@ -0,0 +1,196 @@
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 MigrationContractOptimism {
10
+ // Define struct to hold all UPC minted tokenIds
11
+ struct MintedIds {
12
+ uint256[2] upc3;
13
+ uint256[3] upc4;
14
+ uint256[1] upc11;
15
+ uint256[1] upc17;
16
+ uint256[1] upc19;
17
+ uint256[1] upc25;
18
+ uint256[1] upc44;
19
+ uint256[1] upc47;
20
+ }
21
+
22
+ address[] private transferOwners;
23
+
24
+ constructor(address[] memory _transferOwners) {
25
+ transferOwners = _transferOwners;
26
+ }
27
+
28
+ function executeMigration(
29
+ address hookAddress,
30
+ address resolverAddress,
31
+ address v4HookAddress,
32
+ address v4ResolverAddress,
33
+ address fallbackV4ResolverAddress
34
+ )
35
+ external
36
+ {
37
+ // Validate addresses
38
+ require(hookAddress != address(0), "Hook address not set");
39
+ require(resolverAddress != address(0), "Resolver address not set");
40
+ require(v4HookAddress != address(0), "V4 Hook address not set");
41
+ require(v4ResolverAddress != address(0), "V4 Resolver address not set");
42
+ require(fallbackV4ResolverAddress != address(0), "V4 fallback resolver address not set");
43
+
44
+ JB721TiersHook hook = JB721TiersHook(hookAddress);
45
+ Banny721TokenUriResolver resolver = Banny721TokenUriResolver(resolverAddress);
46
+ IERC721 v4Hook = IERC721(v4HookAddress);
47
+ Banny721TokenUriResolver v4Resolver = Banny721TokenUriResolver(v4ResolverAddress);
48
+ Banny721TokenUriResolver fallbackV4Resolver = Banny721TokenUriResolver(fallbackV4ResolverAddress);
49
+
50
+ // Optimism migration - 11 items
51
+
52
+ // Step 1: Assets are already minted to this contract by the deployer
53
+
54
+ // Assets are already minted to this contract by the deployer
55
+
56
+ // Create and populate the struct
57
+ // Token IDs are generated as: UPC * 1000000000 + unitNumber (where unitNumber starts at 1)
58
+ MintedIds memory sortedMintedIds;
59
+
60
+ // Populate UPC 3 minted tokenIds (2 items)
61
+ for (uint256 i = 0; i < 2; i++) {
62
+ sortedMintedIds.upc3[i] = 3 * 1_000_000_000 + (i + 1);
63
+ }
64
+ // Populate UPC 4 minted tokenIds (3 items)
65
+ for (uint256 i = 0; i < 3; i++) {
66
+ sortedMintedIds.upc4[i] = 4 * 1_000_000_000 + (i + 1);
67
+ }
68
+ // Populate UPC 11 minted tokenIds (1 items)
69
+ for (uint256 i = 0; i < 1; i++) {
70
+ sortedMintedIds.upc11[i] = 11 * 1_000_000_000 + (i + 1);
71
+ }
72
+ // Populate UPC 17 minted tokenIds (1 items)
73
+ for (uint256 i = 0; i < 1; i++) {
74
+ sortedMintedIds.upc17[i] = 17 * 1_000_000_000 + (i + 1);
75
+ }
76
+ // Populate UPC 19 minted tokenIds (1 items)
77
+ for (uint256 i = 0; i < 1; i++) {
78
+ sortedMintedIds.upc19[i] = 19 * 1_000_000_000 + (i + 1);
79
+ }
80
+ // Populate UPC 25 minted tokenIds (1 items)
81
+ for (uint256 i = 0; i < 1; i++) {
82
+ sortedMintedIds.upc25[i] = 25 * 1_000_000_000 + (i + 1);
83
+ }
84
+ // Populate UPC 44 minted tokenIds (1 items)
85
+ for (uint256 i = 0; i < 1; i++) {
86
+ sortedMintedIds.upc44[i] = 44 * 1_000_000_000 + (i + 1);
87
+ }
88
+ // Populate UPC 47 minted tokenIds (1 items)
89
+ for (uint256 i = 0; i < 1; i++) {
90
+ sortedMintedIds.upc47[i] = 47 * 1_000_000_000 + (i + 1);
91
+ }
92
+ // Step 1.5: Approve resolver to transfer all tokens owned by this contract
93
+ // The resolver needs approval to transfer outfits and backgrounds to itself during decoration
94
+ IERC721(address(hook)).setApprovalForAll(address(resolver), true);
95
+
96
+ // Step 2: Process each Banny body and dress them
97
+
98
+ // Dress Banny 3000000001 (Orange)
99
+ {
100
+ uint256[] memory outfitIds = new uint256[](4);
101
+ outfitIds[0] = sortedMintedIds.upc11[0]; // V4: 11000000001 -> V5: sortedMintedIds.upc11[0]
102
+ outfitIds[1] = sortedMintedIds.upc19[0]; // V4: 19000000001 -> V5: sortedMintedIds.upc19[0]
103
+ outfitIds[2] = sortedMintedIds.upc25[0]; // V4: 25000000001 -> V5: sortedMintedIds.upc25[0]
104
+ outfitIds[3] = sortedMintedIds.upc44[0]; // V4: 44000000001 -> V5: sortedMintedIds.upc44[0]
105
+
106
+ resolver.decorateBannyWith(address(hook), 3_000_000_001, 0, outfitIds);
107
+
108
+ MigrationHelper.verifyV4AssetMatch(
109
+ resolver, v4Resolver, fallbackV4Resolver, address(hook), v4HookAddress, 3_000_000_001
110
+ );
111
+ }
112
+
113
+ // Dress Banny 4000000001 (Original)
114
+ {
115
+ uint256[] memory outfitIds = new uint256[](1);
116
+ outfitIds[0] = sortedMintedIds.upc47[0]; // V4: 47000000001 -> V5: sortedMintedIds.upc47[0]
117
+
118
+ resolver.decorateBannyWith(address(hook), 4_000_000_001, 0, outfitIds);
119
+
120
+ MigrationHelper.verifyV4AssetMatch(
121
+ resolver, v4Resolver, fallbackV4Resolver, address(hook), v4HookAddress, 4_000_000_001
122
+ );
123
+ }
124
+
125
+ // Step 3: Transfer all assets to rightful owners using constructor data
126
+ // Generate token IDs in the same order as items appear (matching mint order)
127
+ // Token ID format: UPC * 1000000000 + unitNumber
128
+ uint256[] memory generatedTokenIds = new uint256[](transferOwners.length);
129
+
130
+ generatedTokenIds[0] = 3_000_000_001; // Token ID (V4: 3000000001)
131
+ generatedTokenIds[1] = 3_000_000_002; // Token ID (V4: 3000000002)
132
+ generatedTokenIds[2] = 4_000_000_001; // Token ID (V4: 4000000001)
133
+ generatedTokenIds[3] = 4_000_000_002; // Token ID (V4: 4000000002)
134
+ generatedTokenIds[4] = 4_000_000_003; // Token ID (V4: 4000000003)
135
+ generatedTokenIds[5] = 17_000_000_001; // Token ID (V4: 17000000001)
136
+
137
+ uint256 successfulTransfers = 0;
138
+ uint256 skippedResolverOwned = 0;
139
+
140
+ for (uint256 i = 0; i < transferOwners.length; i++) {
141
+ uint256 tokenId = generatedTokenIds[i];
142
+ // Verify V4 ownership before transferring V5
143
+ address v4Owner = v4Hook.ownerOf(tokenId);
144
+ require(
145
+ v4Owner == transferOwners[i] || v4Owner == address(fallbackV4ResolverAddress),
146
+ "V4/V5 ownership mismatch for token"
147
+ );
148
+
149
+ // Skip transfer if V4 owner is the resolver (resolver holds these tokens, we shouldn't transfer to
150
+ // resolver)
151
+ if (v4Owner == address(v4ResolverAddress) || v4Owner == address(fallbackV4ResolverAddress)) {
152
+ // Token is held by resolver, skip transfer
153
+ skippedResolverOwned++;
154
+ continue;
155
+ }
156
+
157
+ IERC721(address(hook)).transferFrom(address(this), transferOwners[i], tokenId);
158
+ successfulTransfers++;
159
+ }
160
+
161
+ // Verify all expected items were processed (transferred or skipped as expected)
162
+ require(successfulTransfers + skippedResolverOwned == transferOwners.length, "Not all items were processed");
163
+
164
+ // Final verification: Ensure this contract no longer owns any tokens
165
+ // This ensures all transfers completed successfully and no tokens were left behind
166
+ require(hook.balanceOf(address(this)) == 0, "Contract still owns tokens after migration");
167
+
168
+ // Verify tier balances: V5 should never exceed V4 (except for tiers owned by fallback resolver in V4)
169
+
170
+ // Collect unique owners
171
+ address[] memory uniqueOwners = new address[](5);
172
+
173
+ uniqueOwners[0] = 0x25910143C255828F623786f46fe9A8941B7983bB;
174
+ uniqueOwners[1] = 0x292ff025168D2B51f0Ef49f164D281c36761BA2b;
175
+ uniqueOwners[2] = 0xA7a5A2745f10D5C23d75a6fd228A408cEDe1CAE5;
176
+ uniqueOwners[3] = 0x57700212B1cB7b67bD7DF3801DA43CA634513fE0;
177
+ uniqueOwners[4] = 0xA2Fa6144168751D116336B58C5288feaF8bb12C1;
178
+
179
+ // Collect unique tier IDs
180
+ uint256[] memory uniqueTierIds = new uint256[](8);
181
+
182
+ uniqueTierIds[0] = 3;
183
+ uniqueTierIds[1] = 4;
184
+ uniqueTierIds[2] = 11;
185
+ uniqueTierIds[3] = 17;
186
+ uniqueTierIds[4] = 19;
187
+ uniqueTierIds[5] = 25;
188
+ uniqueTierIds[6] = 44;
189
+ uniqueTierIds[7] = 47;
190
+
191
+ // Verify tier balances: V5 should never exceed V4 (except for tiers owned by fallback resolver in V4)
192
+ MigrationHelper.verifyTierBalances(
193
+ hookAddress, v4HookAddress, fallbackV4ResolverAddress, uniqueOwners, uniqueTierIds
194
+ );
195
+ }
196
+ }
@@ -0,0 +1,73 @@
1
+ // SPDX-License-Identifier: MIT
2
+ pragma solidity 0.8.23;
3
+
4
+ import {stdJson} from "forge-std/Script.sol";
5
+ import {Vm} from "forge-std/Vm.sol";
6
+
7
+ import {Banny721TokenUriResolver} from "../../src/Banny721TokenUriResolver.sol";
8
+
9
+ import {SphinxConstants, NetworkInfo} from "@sphinx-labs/contracts/SphinxConstants.sol";
10
+
11
+ struct BannyverseDeployment {
12
+ uint256 revnetId;
13
+ Banny721TokenUriResolver resolver;
14
+ }
15
+
16
+ library BannyverseDeploymentLib {
17
+ // Cheat code address, 0x7109709ECfa91a80626fF3989D68f67F5b1DD12D.
18
+ address internal constant VM_ADDRESS = address(uint160(uint256(keccak256("hevm cheat code"))));
19
+ Vm internal constant vm = Vm(VM_ADDRESS);
20
+
21
+ function getDeployment(string memory path) internal returns (BannyverseDeployment memory deployment) {
22
+ // get chainId for which we need to get the deployment.
23
+ uint256 chainId = block.chainid;
24
+
25
+ // Deploy to get the constants.
26
+ // TODO: get constants without deploy.
27
+ SphinxConstants sphinxConstants = new SphinxConstants();
28
+ NetworkInfo[] memory networks = sphinxConstants.getNetworkInfoArray();
29
+
30
+ for (uint256 _i; _i < networks.length; _i++) {
31
+ if (networks[_i].chainId == chainId) {
32
+ return getDeployment(path, networks[_i].name);
33
+ }
34
+ }
35
+
36
+ revert("ChainID is not (currently) supported by Sphinx.");
37
+ }
38
+
39
+ function getDeployment(
40
+ string memory path,
41
+ string memory network_name
42
+ )
43
+ internal
44
+ view
45
+ returns (BannyverseDeployment memory deployment)
46
+ {
47
+ deployment.resolver = Banny721TokenUriResolver(
48
+ _getDeploymentAddress(path, "banny-core-v5", network_name, "Banny721TokenUriResolver")
49
+ );
50
+
51
+ deployment.revnetId = 4;
52
+ }
53
+
54
+ /// @notice Get the address of a contract that was deployed by the Deploy script.
55
+ /// @dev Reverts if the contract was not found.
56
+ /// @param path The path to the deployment file.
57
+ /// @param contractName The name of the contract to get the address of.
58
+ /// @return The address of the contract.
59
+ function _getDeploymentAddress(
60
+ string memory path,
61
+ string memory project_name,
62
+ string memory network_name,
63
+ string memory contractName
64
+ )
65
+ internal
66
+ view
67
+ returns (address)
68
+ {
69
+ string memory deploymentJson =
70
+ vm.readFile(string.concat(path, project_name, "/", network_name, "/", contractName, ".json"));
71
+ return stdJson.readAddress(deploymentJson, ".address");
72
+ }
73
+ }