@bananapus/suckers-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 (149) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +422 -0
  3. package/SECURITY.md +55 -0
  4. package/SKILLS.md +163 -0
  5. package/deployments/nana-suckers-v5/arbitrum/JBArbitrumSucker.json +1425 -0
  6. package/deployments/nana-suckers-v5/arbitrum/JBArbitrumSuckerDeployer.json +391 -0
  7. package/deployments/nana-suckers-v5/arbitrum/JBCCIPSucker.json +1479 -0
  8. package/deployments/nana-suckers-v5/arbitrum/JBCCIPSuckerDeployer.json +433 -0
  9. package/deployments/nana-suckers-v5/arbitrum/JBCCIPSuckerDeployer_1.json +433 -0
  10. package/deployments/nana-suckers-v5/arbitrum/JBCCIPSuckerDeployer_2.json +433 -0
  11. package/deployments/nana-suckers-v5/arbitrum/JBCCIPSucker_1.json +1479 -0
  12. package/deployments/nana-suckers-v5/arbitrum/JBCCIPSucker_2.json +1479 -0
  13. package/deployments/nana-suckers-v5/arbitrum/JBSuckerRegistry.json +690 -0
  14. package/deployments/nana-suckers-v5/arbitrum_sepolia/JBArbitrumSucker.json +1425 -0
  15. package/deployments/nana-suckers-v5/arbitrum_sepolia/JBArbitrumSuckerDeployer.json +391 -0
  16. package/deployments/nana-suckers-v5/arbitrum_sepolia/JBCCIPSucker.json +1479 -0
  17. package/deployments/nana-suckers-v5/arbitrum_sepolia/JBCCIPSuckerDeployer.json +433 -0
  18. package/deployments/nana-suckers-v5/arbitrum_sepolia/JBCCIPSuckerDeployer_1.json +433 -0
  19. package/deployments/nana-suckers-v5/arbitrum_sepolia/JBCCIPSuckerDeployer_2.json +433 -0
  20. package/deployments/nana-suckers-v5/arbitrum_sepolia/JBCCIPSucker_1.json +1479 -0
  21. package/deployments/nana-suckers-v5/arbitrum_sepolia/JBCCIPSucker_2.json +1479 -0
  22. package/deployments/nana-suckers-v5/arbitrum_sepolia/JBSuckerRegistry.json +690 -0
  23. package/deployments/nana-suckers-v5/base/JBBaseSucker.json +1389 -0
  24. package/deployments/nana-suckers-v5/base/JBBaseSuckerDeployer.json +376 -0
  25. package/deployments/nana-suckers-v5/base/JBCCIPSucker.json +1483 -0
  26. package/deployments/nana-suckers-v5/base/JBCCIPSuckerDeployer.json +436 -0
  27. package/deployments/nana-suckers-v5/base/JBCCIPSuckerDeployer_1.json +436 -0
  28. package/deployments/nana-suckers-v5/base/JBCCIPSuckerDeployer_2.json +436 -0
  29. package/deployments/nana-suckers-v5/base/JBCCIPSucker_1.json +1483 -0
  30. package/deployments/nana-suckers-v5/base/JBCCIPSucker_2.json +1483 -0
  31. package/deployments/nana-suckers-v5/base/JBSuckerRegistry.json +694 -0
  32. package/deployments/nana-suckers-v5/base_sepolia/JBBaseSucker.json +1389 -0
  33. package/deployments/nana-suckers-v5/base_sepolia/JBBaseSuckerDeployer.json +376 -0
  34. package/deployments/nana-suckers-v5/base_sepolia/JBCCIPSucker.json +1483 -0
  35. package/deployments/nana-suckers-v5/base_sepolia/JBCCIPSuckerDeployer.json +436 -0
  36. package/deployments/nana-suckers-v5/base_sepolia/JBCCIPSuckerDeployer_1.json +436 -0
  37. package/deployments/nana-suckers-v5/base_sepolia/JBCCIPSuckerDeployer_2.json +436 -0
  38. package/deployments/nana-suckers-v5/base_sepolia/JBCCIPSucker_1.json +1483 -0
  39. package/deployments/nana-suckers-v5/base_sepolia/JBCCIPSucker_2.json +1483 -0
  40. package/deployments/nana-suckers-v5/base_sepolia/JBSuckerRegistry.json +694 -0
  41. package/deployments/nana-suckers-v5/ethereum/JBArbitrumSucker.json +1429 -0
  42. package/deployments/nana-suckers-v5/ethereum/JBArbitrumSuckerDeployer.json +394 -0
  43. package/deployments/nana-suckers-v5/ethereum/JBBaseSucker.json +1389 -0
  44. package/deployments/nana-suckers-v5/ethereum/JBBaseSuckerDeployer.json +376 -0
  45. package/deployments/nana-suckers-v5/ethereum/JBCCIPSucker.json +1483 -0
  46. package/deployments/nana-suckers-v5/ethereum/JBCCIPSuckerDeployer.json +436 -0
  47. package/deployments/nana-suckers-v5/ethereum/JBCCIPSuckerDeployer_1.json +436 -0
  48. package/deployments/nana-suckers-v5/ethereum/JBCCIPSuckerDeployer_2.json +436 -0
  49. package/deployments/nana-suckers-v5/ethereum/JBCCIPSucker_1.json +1483 -0
  50. package/deployments/nana-suckers-v5/ethereum/JBCCIPSucker_2.json +1483 -0
  51. package/deployments/nana-suckers-v5/ethereum/JBOptimismSucker.json +1389 -0
  52. package/deployments/nana-suckers-v5/ethereum/JBOptimismSuckerDeployer.json +376 -0
  53. package/deployments/nana-suckers-v5/ethereum/JBSuckerRegistry.json +694 -0
  54. package/deployments/nana-suckers-v5/optimism/JBCCIPSucker.json +1479 -0
  55. package/deployments/nana-suckers-v5/optimism/JBCCIPSuckerDeployer.json +433 -0
  56. package/deployments/nana-suckers-v5/optimism/JBCCIPSuckerDeployer_1.json +433 -0
  57. package/deployments/nana-suckers-v5/optimism/JBCCIPSuckerDeployer_2.json +433 -0
  58. package/deployments/nana-suckers-v5/optimism/JBCCIPSucker_1.json +1479 -0
  59. package/deployments/nana-suckers-v5/optimism/JBCCIPSucker_2.json +1479 -0
  60. package/deployments/nana-suckers-v5/optimism/JBOptimismSucker.json +1385 -0
  61. package/deployments/nana-suckers-v5/optimism/JBOptimismSuckerDeployer.json +373 -0
  62. package/deployments/nana-suckers-v5/optimism/JBSuckerRegistry.json +690 -0
  63. package/deployments/nana-suckers-v5/optimism_sepolia/JBCCIPSucker.json +1483 -0
  64. package/deployments/nana-suckers-v5/optimism_sepolia/JBCCIPSuckerDeployer.json +436 -0
  65. package/deployments/nana-suckers-v5/optimism_sepolia/JBCCIPSuckerDeployer_1.json +436 -0
  66. package/deployments/nana-suckers-v5/optimism_sepolia/JBCCIPSuckerDeployer_2.json +436 -0
  67. package/deployments/nana-suckers-v5/optimism_sepolia/JBCCIPSucker_1.json +1483 -0
  68. package/deployments/nana-suckers-v5/optimism_sepolia/JBCCIPSucker_2.json +1483 -0
  69. package/deployments/nana-suckers-v5/optimism_sepolia/JBOptimismSucker.json +1389 -0
  70. package/deployments/nana-suckers-v5/optimism_sepolia/JBOptimismSuckerDeployer.json +376 -0
  71. package/deployments/nana-suckers-v5/optimism_sepolia/JBSuckerRegistry.json +694 -0
  72. package/deployments/nana-suckers-v5/sepolia/JBArbitrumSucker.json +1429 -0
  73. package/deployments/nana-suckers-v5/sepolia/JBArbitrumSuckerDeployer.json +394 -0
  74. package/deployments/nana-suckers-v5/sepolia/JBBaseSucker.json +1389 -0
  75. package/deployments/nana-suckers-v5/sepolia/JBBaseSuckerDeployer.json +376 -0
  76. package/deployments/nana-suckers-v5/sepolia/JBCCIPSucker.json +1483 -0
  77. package/deployments/nana-suckers-v5/sepolia/JBCCIPSuckerDeployer.json +436 -0
  78. package/deployments/nana-suckers-v5/sepolia/JBCCIPSuckerDeployer_1.json +436 -0
  79. package/deployments/nana-suckers-v5/sepolia/JBCCIPSuckerDeployer_2.json +436 -0
  80. package/deployments/nana-suckers-v5/sepolia/JBCCIPSucker_1.json +1483 -0
  81. package/deployments/nana-suckers-v5/sepolia/JBCCIPSucker_2.json +1483 -0
  82. package/deployments/nana-suckers-v5/sepolia/JBOptimismSucker.json +1389 -0
  83. package/deployments/nana-suckers-v5/sepolia/JBOptimismSuckerDeployer.json +376 -0
  84. package/deployments/nana-suckers-v5/sepolia/JBSuckerRegistry.json +694 -0
  85. package/foundry.lock +11 -0
  86. package/foundry.toml +22 -0
  87. package/package.json +33 -0
  88. package/remappings.txt +1 -0
  89. package/script/Deploy.s.sol +506 -0
  90. package/script/helpers/SuckerDeploymentLib.sol +97 -0
  91. package/slither-ci.config.json +10 -0
  92. package/sphinx.lock +476 -0
  93. package/src/JBArbitrumSucker.sol +311 -0
  94. package/src/JBBaseSucker.sol +41 -0
  95. package/src/JBCCIPSucker.sol +303 -0
  96. package/src/JBOptimismSucker.sol +143 -0
  97. package/src/JBSucker.sol +1159 -0
  98. package/src/JBSuckerRegistry.sol +262 -0
  99. package/src/deployers/JBArbitrumSuckerDeployer.sol +86 -0
  100. package/src/deployers/JBBaseSuckerDeployer.sol +26 -0
  101. package/src/deployers/JBCCIPSuckerDeployer.sol +88 -0
  102. package/src/deployers/JBOptimismSuckerDeployer.sol +82 -0
  103. package/src/deployers/JBSuckerDeployer.sol +147 -0
  104. package/src/enums/JBAddToBalanceMode.sol +11 -0
  105. package/src/enums/JBLayer.sol +8 -0
  106. package/src/enums/JBSuckerState.sol +14 -0
  107. package/src/interfaces/IArbGatewayRouter.sol +11 -0
  108. package/src/interfaces/IArbL1GatewayRouter.sol +17 -0
  109. package/src/interfaces/IArbL2GatewayRouter.sol +14 -0
  110. package/src/interfaces/ICCIPRouter.sol +11 -0
  111. package/src/interfaces/IJBArbitrumSucker.sol +13 -0
  112. package/src/interfaces/IJBArbitrumSuckerDeployer.sol +12 -0
  113. package/src/interfaces/IJBCCIPSuckerDeployer.sol +15 -0
  114. package/src/interfaces/IJBOpSuckerDeployer.sol +11 -0
  115. package/src/interfaces/IJBOptimismSucker.sol +10 -0
  116. package/src/interfaces/IJBSucker.sol +144 -0
  117. package/src/interfaces/IJBSuckerDeployer.sol +40 -0
  118. package/src/interfaces/IJBSuckerExtended.sol +22 -0
  119. package/src/interfaces/IJBSuckerRegistry.sol +75 -0
  120. package/src/interfaces/IOPMessenger.sol +18 -0
  121. package/src/interfaces/IOPStandardBridge.sol +29 -0
  122. package/src/interfaces/IWrappedNativeToken.sol +13 -0
  123. package/src/libraries/ARBAddresses.sol +17 -0
  124. package/src/libraries/ARBChains.sol +11 -0
  125. package/src/libraries/CCIPHelper.sol +136 -0
  126. package/src/structs/JBClaim.sol +13 -0
  127. package/src/structs/JBInboxTreeRoot.sol +12 -0
  128. package/src/structs/JBLeaf.sol +14 -0
  129. package/src/structs/JBMessageRoot.sol +16 -0
  130. package/src/structs/JBOutboxTree.sol +18 -0
  131. package/src/structs/JBRemoteToken.sol +17 -0
  132. package/src/structs/JBSuckerDeployerConfig.sol +12 -0
  133. package/src/structs/JBSuckersPair.sol +11 -0
  134. package/src/structs/JBTokenMapping.sol +13 -0
  135. package/src/utils/MerkleLib.sol +1020 -0
  136. package/test/Fork.t.sol +514 -0
  137. package/test/InteropCompat.t.sol +676 -0
  138. package/test/SuckerAttacks.t.sol +509 -0
  139. package/test/SuckerDeepAttacks.t.sol +1563 -0
  140. package/test/mocks/ERC20Mock.sol +36 -0
  141. package/test/mocks/MockMessenger.sol +42 -0
  142. package/test/unit/arb.t.sol +28 -0
  143. package/test/unit/ccip_native_interop.t.sol +719 -0
  144. package/test/unit/ccip_refund.t.sol +234 -0
  145. package/test/unit/deployer.t.sol +475 -0
  146. package/test/unit/emergency.t.sol +305 -0
  147. package/test/unit/merkle.t.sol +212 -0
  148. package/test/unit/multi_chain_evolution.t.sol +622 -0
  149. package/test/unit/registry.t.sol +26 -0
@@ -0,0 +1,475 @@
1
+ // SPDX-License-Identifier: MIT
2
+ pragma solidity ^0.8.13;
3
+
4
+ import "forge-std/Test.sol";
5
+ import /* {*} from */ "@bananapus/core-v6/test/helpers/TestBaseWorkflow.sol";
6
+ import "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol";
7
+
8
+ import {IJBController} from "@bananapus/core-v6/src/interfaces/IJBController.sol";
9
+ import "../../src/JBSucker.sol";
10
+
11
+ import "../../src/deployers/JBOptimismSuckerDeployer.sol";
12
+ import {JBOptimismSucker} from "../../src/JBOptimismSucker.sol";
13
+
14
+ import "../../src/deployers/JBBaseSuckerDeployer.sol";
15
+
16
+ import "../../src/deployers/JBCCIPSuckerDeployer.sol";
17
+ import {JBCCIPSucker} from "../../src/JBCCIPSucker.sol";
18
+
19
+ import "../../src/deployers/JBArbitrumSuckerDeployer.sol";
20
+ import {JBArbitrumSucker} from "../../src/JBArbitrumSucker.sol";
21
+
22
+ import {JBLeaf} from "../../src/structs/JBLeaf.sol";
23
+ import {JBClaim} from "../../src/structs/JBClaim.sol";
24
+ import {JBSuckerDeployerConfig} from "../../src/structs/JBSuckerDeployerConfig.sol";
25
+
26
+ import {JBProjects} from "@bananapus/core-v6/src/JBProjects.sol";
27
+ import {JBDirectory} from "@bananapus/core-v6/src/JBDirectory.sol";
28
+ import {JBPermissions} from "@bananapus/core-v6/src/JBPermissions.sol";
29
+
30
+ import {JBOptimismSuckerDeployer} from "../../src/deployers/JBOptimismSuckerDeployer.sol";
31
+ import {JBSuckerRegistry} from "./../../src/JBSuckerRegistry.sol";
32
+
33
+ contract DeployerTests is Test, TestBaseWorkflow, IERC721Receiver {
34
+ JBSuckerRegistry registry;
35
+ uint256 projectId;
36
+
37
+ //*********************************************************************//
38
+ // --------------------------- Setup --------------------------------- //
39
+ //*********************************************************************//
40
+
41
+ function setUp() public override {
42
+ // Deploy JB.
43
+ super.setUp();
44
+
45
+ // Deploy the registry.
46
+ registry = new JBSuckerRegistry(jbDirectory(), jbPermissions(), address(this), address(0));
47
+
48
+ // Setup: terminal / project
49
+ // Package up the limits for the given terminal.
50
+ JBRulesetMetadata memory _metadata = JBRulesetMetadata({
51
+ reservedPercent: JBConstants.MAX_RESERVED_PERCENT / 2, //50%
52
+ cashOutTaxRate: 0,
53
+ baseCurrency: uint32(uint160(address(JBConstants.NATIVE_TOKEN))),
54
+ pausePay: false,
55
+ pauseCreditTransfers: false,
56
+ allowOwnerMinting: true,
57
+ allowSetCustomToken: false,
58
+ allowTerminalMigration: false,
59
+ allowSetTerminals: false,
60
+ allowSetController: false,
61
+ allowAddAccountingContext: true,
62
+ allowAddPriceFeed: true,
63
+ ownerMustSendPayouts: false,
64
+ holdFees: false,
65
+ useTotalSurplusForCashOuts: true,
66
+ useDataHookForPay: false,
67
+ useDataHookForCashOut: false,
68
+ dataHook: address(0),
69
+ metadata: 0
70
+ });
71
+
72
+ JBFundAccessLimitGroup[] memory _fundAccessLimitGroup = new JBFundAccessLimitGroup[](1);
73
+
74
+ // Specify a payout limit.
75
+ JBCurrencyAmount[] memory _payoutLimits = new JBCurrencyAmount[](0);
76
+
77
+ // Specify a surplus allowance.
78
+ JBCurrencyAmount[] memory _surplusAllowances = new JBCurrencyAmount[](1);
79
+ _surplusAllowances[0] =
80
+ JBCurrencyAmount({amount: 5 * 10 ** 18, currency: uint32(uint160(JBConstants.NATIVE_TOKEN))});
81
+
82
+ _fundAccessLimitGroup[0] = JBFundAccessLimitGroup({
83
+ terminal: address(jbMultiTerminal()),
84
+ token: JBConstants.NATIVE_TOKEN,
85
+ payoutLimits: _payoutLimits,
86
+ surplusAllowances: _surplusAllowances
87
+ });
88
+
89
+ // Package up the ruleset configuration.
90
+ JBRulesetConfig[] memory _rulesetConfigurations = new JBRulesetConfig[](1);
91
+ _rulesetConfigurations[0].mustStartAtOrAfter = 0;
92
+ _rulesetConfigurations[0].duration = 0;
93
+ _rulesetConfigurations[0].weight = 1000 * 10 ** 18;
94
+ _rulesetConfigurations[0].weightCutPercent = 0;
95
+ _rulesetConfigurations[0].approvalHook = IJBRulesetApprovalHook(address(0));
96
+ _rulesetConfigurations[0].metadata = _metadata;
97
+ _rulesetConfigurations[0].splitGroups = new JBSplitGroup[](0);
98
+ _rulesetConfigurations[0].fundAccessLimitGroups = _fundAccessLimitGroup;
99
+
100
+ JBTerminalConfig[] memory _terminalConfigurations = new JBTerminalConfig[](1);
101
+ JBAccountingContext[] memory _tokensToAccept = new JBAccountingContext[](1);
102
+
103
+ _tokensToAccept[0] = JBAccountingContext({
104
+ token: JBConstants.NATIVE_TOKEN, decimals: 18, currency: uint32(uint160(JBConstants.NATIVE_TOKEN))
105
+ });
106
+
107
+ _terminalConfigurations[0] =
108
+ JBTerminalConfig({terminal: jbMultiTerminal(), accountingContextsToAccept: _tokensToAccept});
109
+
110
+ // Create a first project to collect fees.
111
+ projectId = jbController()
112
+ .launchProjectFor({
113
+ owner: address(this),
114
+ projectUri: "whatever",
115
+ rulesetConfigurations: _rulesetConfigurations,
116
+ terminalConfigurations: _terminalConfigurations, // Set terminals to receive fees.
117
+ memo: ""
118
+ });
119
+
120
+ // Setup an erc20 for the project
121
+ jbController().deployERC20For(1, "SuckerToken", "SOOK", bytes32(0));
122
+ }
123
+
124
+ function _setupOptimismDeployer(
125
+ IOPMessenger _opMessenger,
126
+ IOPStandardBridge _opBridge
127
+ )
128
+ internal
129
+ returns (IJBSuckerDeployer deployer)
130
+ {
131
+ vm.assume(address(_opMessenger) != address(0));
132
+ vm.assume(address(_opBridge) != address(0));
133
+
134
+ JBOptimismSuckerDeployer OPDeployer = new JBOptimismSuckerDeployer({
135
+ directory: jbDirectory(),
136
+ permissions: jbPermissions(),
137
+ tokens: jbTokens(),
138
+ configurator: address(this),
139
+ trustedForwarder: address(0)
140
+ });
141
+
142
+ deployer = OPDeployer;
143
+ OPDeployer.setChainSpecificConstants(_opMessenger, _opBridge);
144
+
145
+ // Deploy the singleton.
146
+ JBOptimismSucker sucker = new JBOptimismSucker({
147
+ deployer: OPDeployer,
148
+ directory: jbDirectory(),
149
+ permissions: jbPermissions(),
150
+ tokens: jbTokens(),
151
+ addToBalanceMode: JBAddToBalanceMode.MANUAL,
152
+ trustedForwarder: address(0)
153
+ });
154
+
155
+ // Set the singleton.
156
+ OPDeployer.configureSingleton(sucker);
157
+
158
+ assertEq(address(OPDeployer.opMessenger()), address(_opMessenger));
159
+ assertEq(address(OPDeployer.opBridge()), address(_opBridge));
160
+ }
161
+
162
+ function _setupCCIPDeployer(
163
+ uint256 _remoteChainId,
164
+ uint64 _remoteChainSelector,
165
+ ICCIPRouter _ccipRouter
166
+ )
167
+ internal
168
+ returns (IJBSuckerDeployer deployer)
169
+ {
170
+ JBCCIPSuckerDeployer CCIPDeployer = new JBCCIPSuckerDeployer({
171
+ directory: jbDirectory(),
172
+ permissions: jbPermissions(),
173
+ tokens: jbTokens(),
174
+ configurator: address(this),
175
+ trustedForwarder: address(0)
176
+ });
177
+
178
+ deployer = CCIPDeployer;
179
+ CCIPDeployer.setChainSpecificConstants({
180
+ remoteChainId: _remoteChainId, remoteChainSelector: _remoteChainSelector, router: _ccipRouter
181
+ });
182
+
183
+ // Deploy the singleton.
184
+ JBCCIPSucker sucker = new JBCCIPSucker({
185
+ deployer: CCIPDeployer,
186
+ directory: jbDirectory(),
187
+ permissions: jbPermissions(),
188
+ tokens: jbTokens(),
189
+ addToBalanceMode: JBAddToBalanceMode.MANUAL,
190
+ trustedForwarder: address(0)
191
+ });
192
+
193
+ // Set the singleton.
194
+ CCIPDeployer.configureSingleton(sucker);
195
+
196
+ assertEq(CCIPDeployer.ccipRemoteChainId(), _remoteChainId);
197
+ assertEq(CCIPDeployer.ccipRemoteChainSelector(), _remoteChainSelector);
198
+ assertEq(address(CCIPDeployer.ccipRouter()), address(_ccipRouter));
199
+ }
200
+
201
+ function _setupArbitrumDeployer(
202
+ JBLayer _layer,
203
+ IInbox _inbox,
204
+ IArbGatewayRouter _gatewayRouter
205
+ )
206
+ internal
207
+ returns (IJBSuckerDeployer deployer)
208
+ {
209
+ JBArbitrumSuckerDeployer ARBDeployer = new JBArbitrumSuckerDeployer({
210
+ directory: jbDirectory(),
211
+ permissions: jbPermissions(),
212
+ tokens: jbTokens(),
213
+ configurator: address(this),
214
+ trustedForwarder: address(0)
215
+ });
216
+
217
+ deployer = ARBDeployer;
218
+ ARBDeployer.setChainSpecificConstants(_layer, _inbox, _gatewayRouter);
219
+
220
+ // Deploy the singleton.
221
+ JBArbitrumSucker sucker = new JBArbitrumSucker({
222
+ deployer: ARBDeployer,
223
+ directory: jbDirectory(),
224
+ permissions: jbPermissions(),
225
+ tokens: jbTokens(),
226
+ addToBalanceMode: JBAddToBalanceMode.MANUAL,
227
+ trustedForwarder: address(0)
228
+ });
229
+
230
+ // Set the singleton.
231
+ ARBDeployer.configureSingleton(sucker);
232
+
233
+ assertEq(uint256(ARBDeployer.arbLayer()), uint256(_layer));
234
+ assertEq(address(ARBDeployer.arbInbox()), address(_inbox));
235
+ assertEq(address(ARBDeployer.arbGatewayRouter()), address(_gatewayRouter));
236
+ }
237
+
238
+ //*********************************************************************//
239
+ // ------------------------ Variations ------------------------------- //
240
+ //*********************************************************************//
241
+
242
+ function testOPDeployer(IOPMessenger _opMessenger, IOPStandardBridge _opBridge) public {
243
+ IJBSuckerDeployer deployer = _setupOptimismDeployer(_opMessenger, _opBridge);
244
+ IJBSucker sucker = _deployDirectly(deployer, projectId, bytes32(0));
245
+ _assertValidSucker(sucker, projectId);
246
+ _assertOptimismSucker(deployer, sucker);
247
+ }
248
+
249
+ function testOPDeployerThroughRegistry(IOPMessenger _opMessenger, IOPStandardBridge _opBridge) public {
250
+ IJBSuckerDeployer deployer = _addToRegistry(_setupOptimismDeployer(_opMessenger, _opBridge));
251
+ _allowMapping(projectId, address(registry));
252
+ IJBSucker sucker = _deployThroughRegistry(deployer, projectId, bytes32(0));
253
+ _assertRegistered(_assertValidSucker(sucker, projectId));
254
+ _assertOptimismSucker(deployer, sucker);
255
+ }
256
+
257
+ function testCCIPDeployer(uint256 _remoteChainId, uint64 _remoteChainSelector, ICCIPRouter _ccipRouter) public {
258
+ // Ensure that the id/selector are set.
259
+ vm.assume(_remoteChainSelector != 0);
260
+ vm.assume(_remoteChainId != 0);
261
+
262
+ // Ensure that its not a precompile.
263
+ vm.assume(uint160(address(_ccipRouter)) > 100);
264
+
265
+ // Exclude deployed contracts to prevent vm.etch from overwriting them.
266
+ _assumeNotDeployed(address(_ccipRouter));
267
+
268
+ // We have a sanity check that requires code to be at the router address.
269
+ vm.etch(address(_ccipRouter), "0x1");
270
+
271
+ IJBSuckerDeployer deployer = _setupCCIPDeployer(_remoteChainId, _remoteChainSelector, _ccipRouter);
272
+ IJBSucker sucker = _deployDirectly(deployer, projectId, bytes32(0));
273
+ _assertValidSucker(sucker, projectId);
274
+ _assertCCIPSucker(deployer, sucker);
275
+ }
276
+
277
+ function testCCIPDeployerThroughRegistry(
278
+ uint256 _remoteChainId,
279
+ uint64 _remoteChainSelector,
280
+ ICCIPRouter _ccipRouter
281
+ )
282
+ public
283
+ {
284
+ // Ensure that the id/selector are set.
285
+ vm.assume(_remoteChainSelector != 0);
286
+ vm.assume(_remoteChainId != 0);
287
+
288
+ // Ensure that its not a precompile.
289
+ vm.assume(uint160(address(_ccipRouter)) > 100);
290
+
291
+ // Exclude deployed contracts to prevent vm.etch from overwriting them.
292
+ _assumeNotDeployed(address(_ccipRouter));
293
+
294
+ // We have a sanity check that requires code to be at the router address.
295
+ vm.etch(address(_ccipRouter), "0x1");
296
+
297
+ _allowMapping(projectId, address(registry));
298
+ IJBSuckerDeployer deployer =
299
+ _addToRegistry(_setupCCIPDeployer(_remoteChainId, _remoteChainSelector, _ccipRouter));
300
+ IJBSucker sucker = _deployThroughRegistry(deployer, projectId, bytes32(0));
301
+ _assertRegistered(_assertValidSucker(sucker, projectId));
302
+ _assertCCIPSucker(deployer, sucker);
303
+ }
304
+
305
+ function testArbDeployer(bool _layer, IInbox _inbox, IArbGatewayRouter _gatewayRouter) public {
306
+ // All of these must be set for a valid configuration.
307
+ vm.assume(_inbox != IInbox(address(0)) && _gatewayRouter != IArbGatewayRouter(address(0)));
308
+
309
+ IJBSuckerDeployer deployer = _setupArbitrumDeployer(_layer ? JBLayer.L1 : JBLayer.L2, _inbox, _gatewayRouter);
310
+ IJBSucker sucker = _deployDirectly(deployer, projectId, bytes32(0));
311
+ _assertValidSucker(sucker, projectId);
312
+ _assertArbSucker(deployer, sucker);
313
+ }
314
+
315
+ function testArbDeployerThroughRegistry(bool _layer, IInbox _inbox, IArbGatewayRouter _gatewayRouter) public {
316
+ // All of these must be set for a valid configuration.
317
+ vm.assume(_inbox != IInbox(address(0)) && _gatewayRouter != IArbGatewayRouter(address(0)));
318
+
319
+ _allowMapping(projectId, address(registry));
320
+ IJBSuckerDeployer deployer =
321
+ _addToRegistry(_setupArbitrumDeployer(_layer ? JBLayer.L1 : JBLayer.L2, _inbox, _gatewayRouter));
322
+ IJBSucker sucker = _deployThroughRegistry(deployer, projectId, bytes32(0));
323
+ _assertRegistered(_assertValidSucker(sucker, projectId));
324
+ _assertArbSucker(deployer, sucker);
325
+ }
326
+
327
+ //*********************************************************************//
328
+ // ------------------------ Utilities ------------------------------- //
329
+ //*********************************************************************//
330
+
331
+ function _addToRegistry(IJBSuckerDeployer deployer) internal returns (IJBSuckerDeployer) {
332
+ registry.allowSuckerDeployer(address(deployer));
333
+
334
+ // lets us chain calls.
335
+ return deployer;
336
+ }
337
+
338
+ function _allowMapping(uint256 _projectId, address beneficiary) internal {
339
+ uint8[] memory permissions = new uint8[](1);
340
+ permissions[0] = JBPermissionIds.MAP_SUCKER_TOKEN;
341
+
342
+ jbPermissions()
343
+ .setPermissionsFor(
344
+ address(this),
345
+ JBPermissionsData({operator: beneficiary, projectId: uint56(_projectId), permissionIds: permissions})
346
+ );
347
+ }
348
+
349
+ function _allowDeploying(uint256 _projectId, address beneficiary) internal {
350
+ uint8[] memory permissions = new uint8[](1);
351
+ permissions[0] = JBPermissionIds.DEPLOY_SUCKERS;
352
+
353
+ jbPermissions()
354
+ .setPermissionsFor(
355
+ address(this),
356
+ JBPermissionsData({operator: beneficiary, projectId: uint56(_projectId), permissionIds: permissions})
357
+ );
358
+ }
359
+
360
+ function _deployDirectly(IJBSuckerDeployer deployer, uint256 _projectId, bytes32 salt)
361
+ internal
362
+ returns (IJBSucker)
363
+ {
364
+ return deployer.createForSender(_projectId, salt);
365
+ }
366
+
367
+ function _deployThroughRegistry(
368
+ IJBSuckerDeployer deployer,
369
+ uint256 _projectId,
370
+ bytes32 salt
371
+ )
372
+ internal
373
+ returns (IJBSucker)
374
+ {
375
+ JBTokenMapping[] memory mappings = new JBTokenMapping[](1);
376
+ mappings[0] = JBTokenMapping({
377
+ localToken: address(JBConstants.NATIVE_TOKEN),
378
+ minGas: 300_000,
379
+ remoteToken: bytes32(uint256(uint160(JBConstants.NATIVE_TOKEN))),
380
+ minBridgeAmount: 0.1 ether
381
+ });
382
+
383
+ JBSuckerDeployerConfig[] memory configurations = new JBSuckerDeployerConfig[](1);
384
+ configurations[0] = JBSuckerDeployerConfig({deployer: deployer, mappings: mappings});
385
+
386
+ return IJBSucker(registry.deploySuckersFor(_projectId, salt, configurations)[0]);
387
+ }
388
+
389
+ /// @notice Exclude addresses of contracts deployed during setUp to prevent vm.etch from overwriting them.
390
+ function _assumeNotDeployed(address addr) internal view {
391
+ vm.assume(addr != address(jbPermissions()));
392
+ vm.assume(addr != address(jbDirectory()));
393
+ vm.assume(addr != address(jbProjects()));
394
+ vm.assume(addr != address(jbController()));
395
+ vm.assume(addr != address(jbMultiTerminal()));
396
+ vm.assume(addr != address(jbTokens()));
397
+ vm.assume(addr != address(jbSplits()));
398
+ vm.assume(addr != address(jbRulesets()));
399
+ vm.assume(addr != address(jbTerminalStore()));
400
+ vm.assume(addr != address(registry));
401
+ }
402
+
403
+ //*********************************************************************//
404
+ // -------------------------- Asserts -------------------------------- //
405
+ //*********************************************************************//
406
+
407
+ function _assertValidSucker(IJBSucker sucker, uint256 _projectId) internal view returns (IJBSucker) {
408
+ assertEq(sucker.projectId(), _projectId);
409
+ assertEq(address(sucker.DIRECTORY()), address(jbDirectory()));
410
+ assertEq(address(sucker.TOKENS()), address(jbTokens()));
411
+ assertEq(sucker.peer(), bytes32(uint256(uint160(address(sucker)))));
412
+ assertEq(uint8(sucker.state()), uint8(JBSuckerState.ENABLED));
413
+
414
+ return sucker;
415
+ }
416
+
417
+ function _assertRegistered(IJBSucker sucker) internal view returns (IJBSucker) {
418
+ uint256 _projectId = sucker.projectId();
419
+ assert(registry.isSuckerOf(_projectId, address(sucker)));
420
+ assertEq(address(registry.suckersOf(_projectId)[0]), address(sucker));
421
+ return sucker;
422
+ }
423
+
424
+ function _assertOptimismSucker(IJBSuckerDeployer deployer, IJBSucker sucker) internal view returns (IJBSucker) {
425
+ assertEq(
426
+ address(JBOptimismSuckerDeployer(address(deployer)).opMessenger()),
427
+ address(JBOptimismSucker(payable(address(sucker))).OPMESSENGER())
428
+ );
429
+ assertEq(
430
+ address(JBOptimismSuckerDeployer(address(deployer)).opBridge()),
431
+ address(JBOptimismSucker(payable(address(sucker))).OPBRIDGE())
432
+ );
433
+
434
+ return sucker;
435
+ }
436
+
437
+ function _assertCCIPSucker(IJBSuckerDeployer deployer, IJBSucker sucker) internal view returns (IJBSucker) {
438
+ assertEq(
439
+ address(JBCCIPSuckerDeployer(address(deployer)).ccipRouter()),
440
+ address(JBCCIPSucker(payable(address(sucker))).CCIP_ROUTER())
441
+ );
442
+
443
+ assertEq(
444
+ JBCCIPSuckerDeployer(address(deployer)).ccipRemoteChainId(),
445
+ JBCCIPSucker(payable(address(sucker))).REMOTE_CHAIN_ID()
446
+ );
447
+
448
+ assertEq(
449
+ JBCCIPSuckerDeployer(address(deployer)).ccipRemoteChainSelector(),
450
+ JBCCIPSucker(payable(address(sucker))).REMOTE_CHAIN_SELECTOR()
451
+ );
452
+ return sucker;
453
+ }
454
+
455
+ function _assertArbSucker(IJBSuckerDeployer deployer, IJBSucker sucker) internal view returns (IJBSucker) {
456
+ assertEq(
457
+ uint256(JBArbitrumSuckerDeployer(address(deployer)).arbLayer()),
458
+ uint256(JBArbitrumSucker(payable(address(sucker))).LAYER())
459
+ );
460
+ assertEq(
461
+ address(JBArbitrumSuckerDeployer(address(deployer)).arbInbox()),
462
+ address(JBArbitrumSucker(payable(address(sucker))).ARBINBOX())
463
+ );
464
+ assertEq(
465
+ address(JBArbitrumSuckerDeployer(address(deployer)).arbGatewayRouter()),
466
+ address(JBArbitrumSucker(payable(address(sucker))).GATEWAYROUTER())
467
+ );
468
+ return sucker;
469
+ }
470
+
471
+ /// @notice This function is called when we create a JB project.
472
+ function onERC721Received(address, address, uint256, bytes calldata) external pure returns (bytes4) {
473
+ return IERC721Receiver.onERC721Received.selector;
474
+ }
475
+ }