@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.
- package/LICENSE +21 -0
- package/README.md +422 -0
- package/SECURITY.md +55 -0
- package/SKILLS.md +163 -0
- package/deployments/nana-suckers-v5/arbitrum/JBArbitrumSucker.json +1425 -0
- package/deployments/nana-suckers-v5/arbitrum/JBArbitrumSuckerDeployer.json +391 -0
- package/deployments/nana-suckers-v5/arbitrum/JBCCIPSucker.json +1479 -0
- package/deployments/nana-suckers-v5/arbitrum/JBCCIPSuckerDeployer.json +433 -0
- package/deployments/nana-suckers-v5/arbitrum/JBCCIPSuckerDeployer_1.json +433 -0
- package/deployments/nana-suckers-v5/arbitrum/JBCCIPSuckerDeployer_2.json +433 -0
- package/deployments/nana-suckers-v5/arbitrum/JBCCIPSucker_1.json +1479 -0
- package/deployments/nana-suckers-v5/arbitrum/JBCCIPSucker_2.json +1479 -0
- package/deployments/nana-suckers-v5/arbitrum/JBSuckerRegistry.json +690 -0
- package/deployments/nana-suckers-v5/arbitrum_sepolia/JBArbitrumSucker.json +1425 -0
- package/deployments/nana-suckers-v5/arbitrum_sepolia/JBArbitrumSuckerDeployer.json +391 -0
- package/deployments/nana-suckers-v5/arbitrum_sepolia/JBCCIPSucker.json +1479 -0
- package/deployments/nana-suckers-v5/arbitrum_sepolia/JBCCIPSuckerDeployer.json +433 -0
- package/deployments/nana-suckers-v5/arbitrum_sepolia/JBCCIPSuckerDeployer_1.json +433 -0
- package/deployments/nana-suckers-v5/arbitrum_sepolia/JBCCIPSuckerDeployer_2.json +433 -0
- package/deployments/nana-suckers-v5/arbitrum_sepolia/JBCCIPSucker_1.json +1479 -0
- package/deployments/nana-suckers-v5/arbitrum_sepolia/JBCCIPSucker_2.json +1479 -0
- package/deployments/nana-suckers-v5/arbitrum_sepolia/JBSuckerRegistry.json +690 -0
- package/deployments/nana-suckers-v5/base/JBBaseSucker.json +1389 -0
- package/deployments/nana-suckers-v5/base/JBBaseSuckerDeployer.json +376 -0
- package/deployments/nana-suckers-v5/base/JBCCIPSucker.json +1483 -0
- package/deployments/nana-suckers-v5/base/JBCCIPSuckerDeployer.json +436 -0
- package/deployments/nana-suckers-v5/base/JBCCIPSuckerDeployer_1.json +436 -0
- package/deployments/nana-suckers-v5/base/JBCCIPSuckerDeployer_2.json +436 -0
- package/deployments/nana-suckers-v5/base/JBCCIPSucker_1.json +1483 -0
- package/deployments/nana-suckers-v5/base/JBCCIPSucker_2.json +1483 -0
- package/deployments/nana-suckers-v5/base/JBSuckerRegistry.json +694 -0
- package/deployments/nana-suckers-v5/base_sepolia/JBBaseSucker.json +1389 -0
- package/deployments/nana-suckers-v5/base_sepolia/JBBaseSuckerDeployer.json +376 -0
- package/deployments/nana-suckers-v5/base_sepolia/JBCCIPSucker.json +1483 -0
- package/deployments/nana-suckers-v5/base_sepolia/JBCCIPSuckerDeployer.json +436 -0
- package/deployments/nana-suckers-v5/base_sepolia/JBCCIPSuckerDeployer_1.json +436 -0
- package/deployments/nana-suckers-v5/base_sepolia/JBCCIPSuckerDeployer_2.json +436 -0
- package/deployments/nana-suckers-v5/base_sepolia/JBCCIPSucker_1.json +1483 -0
- package/deployments/nana-suckers-v5/base_sepolia/JBCCIPSucker_2.json +1483 -0
- package/deployments/nana-suckers-v5/base_sepolia/JBSuckerRegistry.json +694 -0
- package/deployments/nana-suckers-v5/ethereum/JBArbitrumSucker.json +1429 -0
- package/deployments/nana-suckers-v5/ethereum/JBArbitrumSuckerDeployer.json +394 -0
- package/deployments/nana-suckers-v5/ethereum/JBBaseSucker.json +1389 -0
- package/deployments/nana-suckers-v5/ethereum/JBBaseSuckerDeployer.json +376 -0
- package/deployments/nana-suckers-v5/ethereum/JBCCIPSucker.json +1483 -0
- package/deployments/nana-suckers-v5/ethereum/JBCCIPSuckerDeployer.json +436 -0
- package/deployments/nana-suckers-v5/ethereum/JBCCIPSuckerDeployer_1.json +436 -0
- package/deployments/nana-suckers-v5/ethereum/JBCCIPSuckerDeployer_2.json +436 -0
- package/deployments/nana-suckers-v5/ethereum/JBCCIPSucker_1.json +1483 -0
- package/deployments/nana-suckers-v5/ethereum/JBCCIPSucker_2.json +1483 -0
- package/deployments/nana-suckers-v5/ethereum/JBOptimismSucker.json +1389 -0
- package/deployments/nana-suckers-v5/ethereum/JBOptimismSuckerDeployer.json +376 -0
- package/deployments/nana-suckers-v5/ethereum/JBSuckerRegistry.json +694 -0
- package/deployments/nana-suckers-v5/optimism/JBCCIPSucker.json +1479 -0
- package/deployments/nana-suckers-v5/optimism/JBCCIPSuckerDeployer.json +433 -0
- package/deployments/nana-suckers-v5/optimism/JBCCIPSuckerDeployer_1.json +433 -0
- package/deployments/nana-suckers-v5/optimism/JBCCIPSuckerDeployer_2.json +433 -0
- package/deployments/nana-suckers-v5/optimism/JBCCIPSucker_1.json +1479 -0
- package/deployments/nana-suckers-v5/optimism/JBCCIPSucker_2.json +1479 -0
- package/deployments/nana-suckers-v5/optimism/JBOptimismSucker.json +1385 -0
- package/deployments/nana-suckers-v5/optimism/JBOptimismSuckerDeployer.json +373 -0
- package/deployments/nana-suckers-v5/optimism/JBSuckerRegistry.json +690 -0
- package/deployments/nana-suckers-v5/optimism_sepolia/JBCCIPSucker.json +1483 -0
- package/deployments/nana-suckers-v5/optimism_sepolia/JBCCIPSuckerDeployer.json +436 -0
- package/deployments/nana-suckers-v5/optimism_sepolia/JBCCIPSuckerDeployer_1.json +436 -0
- package/deployments/nana-suckers-v5/optimism_sepolia/JBCCIPSuckerDeployer_2.json +436 -0
- package/deployments/nana-suckers-v5/optimism_sepolia/JBCCIPSucker_1.json +1483 -0
- package/deployments/nana-suckers-v5/optimism_sepolia/JBCCIPSucker_2.json +1483 -0
- package/deployments/nana-suckers-v5/optimism_sepolia/JBOptimismSucker.json +1389 -0
- package/deployments/nana-suckers-v5/optimism_sepolia/JBOptimismSuckerDeployer.json +376 -0
- package/deployments/nana-suckers-v5/optimism_sepolia/JBSuckerRegistry.json +694 -0
- package/deployments/nana-suckers-v5/sepolia/JBArbitrumSucker.json +1429 -0
- package/deployments/nana-suckers-v5/sepolia/JBArbitrumSuckerDeployer.json +394 -0
- package/deployments/nana-suckers-v5/sepolia/JBBaseSucker.json +1389 -0
- package/deployments/nana-suckers-v5/sepolia/JBBaseSuckerDeployer.json +376 -0
- package/deployments/nana-suckers-v5/sepolia/JBCCIPSucker.json +1483 -0
- package/deployments/nana-suckers-v5/sepolia/JBCCIPSuckerDeployer.json +436 -0
- package/deployments/nana-suckers-v5/sepolia/JBCCIPSuckerDeployer_1.json +436 -0
- package/deployments/nana-suckers-v5/sepolia/JBCCIPSuckerDeployer_2.json +436 -0
- package/deployments/nana-suckers-v5/sepolia/JBCCIPSucker_1.json +1483 -0
- package/deployments/nana-suckers-v5/sepolia/JBCCIPSucker_2.json +1483 -0
- package/deployments/nana-suckers-v5/sepolia/JBOptimismSucker.json +1389 -0
- package/deployments/nana-suckers-v5/sepolia/JBOptimismSuckerDeployer.json +376 -0
- package/deployments/nana-suckers-v5/sepolia/JBSuckerRegistry.json +694 -0
- package/foundry.lock +11 -0
- package/foundry.toml +22 -0
- package/package.json +33 -0
- package/remappings.txt +1 -0
- package/script/Deploy.s.sol +506 -0
- package/script/helpers/SuckerDeploymentLib.sol +97 -0
- package/slither-ci.config.json +10 -0
- package/sphinx.lock +476 -0
- package/src/JBArbitrumSucker.sol +311 -0
- package/src/JBBaseSucker.sol +41 -0
- package/src/JBCCIPSucker.sol +303 -0
- package/src/JBOptimismSucker.sol +143 -0
- package/src/JBSucker.sol +1159 -0
- package/src/JBSuckerRegistry.sol +262 -0
- package/src/deployers/JBArbitrumSuckerDeployer.sol +86 -0
- package/src/deployers/JBBaseSuckerDeployer.sol +26 -0
- package/src/deployers/JBCCIPSuckerDeployer.sol +88 -0
- package/src/deployers/JBOptimismSuckerDeployer.sol +82 -0
- package/src/deployers/JBSuckerDeployer.sol +147 -0
- package/src/enums/JBAddToBalanceMode.sol +11 -0
- package/src/enums/JBLayer.sol +8 -0
- package/src/enums/JBSuckerState.sol +14 -0
- package/src/interfaces/IArbGatewayRouter.sol +11 -0
- package/src/interfaces/IArbL1GatewayRouter.sol +17 -0
- package/src/interfaces/IArbL2GatewayRouter.sol +14 -0
- package/src/interfaces/ICCIPRouter.sol +11 -0
- package/src/interfaces/IJBArbitrumSucker.sol +13 -0
- package/src/interfaces/IJBArbitrumSuckerDeployer.sol +12 -0
- package/src/interfaces/IJBCCIPSuckerDeployer.sol +15 -0
- package/src/interfaces/IJBOpSuckerDeployer.sol +11 -0
- package/src/interfaces/IJBOptimismSucker.sol +10 -0
- package/src/interfaces/IJBSucker.sol +144 -0
- package/src/interfaces/IJBSuckerDeployer.sol +40 -0
- package/src/interfaces/IJBSuckerExtended.sol +22 -0
- package/src/interfaces/IJBSuckerRegistry.sol +75 -0
- package/src/interfaces/IOPMessenger.sol +18 -0
- package/src/interfaces/IOPStandardBridge.sol +29 -0
- package/src/interfaces/IWrappedNativeToken.sol +13 -0
- package/src/libraries/ARBAddresses.sol +17 -0
- package/src/libraries/ARBChains.sol +11 -0
- package/src/libraries/CCIPHelper.sol +136 -0
- package/src/structs/JBClaim.sol +13 -0
- package/src/structs/JBInboxTreeRoot.sol +12 -0
- package/src/structs/JBLeaf.sol +14 -0
- package/src/structs/JBMessageRoot.sol +16 -0
- package/src/structs/JBOutboxTree.sol +18 -0
- package/src/structs/JBRemoteToken.sol +17 -0
- package/src/structs/JBSuckerDeployerConfig.sol +12 -0
- package/src/structs/JBSuckersPair.sol +11 -0
- package/src/structs/JBTokenMapping.sol +13 -0
- package/src/utils/MerkleLib.sol +1020 -0
- package/test/Fork.t.sol +514 -0
- package/test/InteropCompat.t.sol +676 -0
- package/test/SuckerAttacks.t.sol +509 -0
- package/test/SuckerDeepAttacks.t.sol +1563 -0
- package/test/mocks/ERC20Mock.sol +36 -0
- package/test/mocks/MockMessenger.sol +42 -0
- package/test/unit/arb.t.sol +28 -0
- package/test/unit/ccip_native_interop.t.sol +719 -0
- package/test/unit/ccip_refund.t.sol +234 -0
- package/test/unit/deployer.t.sol +475 -0
- package/test/unit/emergency.t.sol +305 -0
- package/test/unit/merkle.t.sol +212 -0
- package/test/unit/multi_chain_evolution.t.sol +622 -0
- 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
|
+
}
|