@bananapus/omnichain-deployers-v6 0.0.19 → 0.0.21
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/ADMINISTRATION.md +30 -2
- package/ARCHITECTURE.md +48 -85
- package/AUDIT_INSTRUCTIONS.md +52 -366
- package/CHANGELOG.md +61 -0
- package/README.md +45 -189
- package/RISKS.md +23 -6
- package/SKILLS.md +27 -240
- package/STYLE_GUIDE.md +71 -19
- package/USER_JOURNEYS.md +45 -417
- package/package.json +4 -5
- package/references/operations.md +28 -0
- package/references/runtime.md +28 -0
- package/src/JBOmnichainDeployer.sol +7 -2
- package/src/interfaces/IJBOmnichainDeployer.sol +3 -0
- package/test/JBOmnichainDeployer.t.sol +23 -0
- package/test/OmnichainDeployerEdgeCases.t.sol +10 -1
- package/test/TestAuditGaps.sol +23 -0
- package/test/audit/CarryForwardRejectedHook.t.sol +305 -0
- package/test/audit/JBOmnichainDeployer.t.sol +10 -0
- package/test/fork/OmnichainForkTestBase.sol +10 -7
- package/test/fork/TestOmnichain721QueueAndAdjust.t.sol +28 -21
- package/CHANGE_LOG.md +0 -341
- package/assets/findings/nana-omnichain-deployers-v6-pashov-ai-audit-report-20260330-103536.md +0 -39
|
@@ -614,11 +614,20 @@ contract OmnichainDeployerEdgeCases is Test {
|
|
|
614
614
|
abi.encode(uint256(50)) // A past ruleset ID — no hook stored at this ID
|
|
615
615
|
);
|
|
616
616
|
|
|
617
|
+
// Mock currentOf to return a ruleset with id=50 (no hook stored for this id via the deployer).
|
|
618
|
+
JBRuleset memory currentRuleset;
|
|
619
|
+
currentRuleset.id = uint48(50);
|
|
620
|
+
vm.mockCall(
|
|
621
|
+
address(rulesets),
|
|
622
|
+
abi.encodeWithSelector(IJBRulesets.currentOf.selector, projectId),
|
|
623
|
+
abi.encode(currentRuleset)
|
|
624
|
+
);
|
|
625
|
+
|
|
617
626
|
JBRulesetConfig[] memory configs = new JBRulesetConfig[](1);
|
|
618
627
|
configs[0] = _makeRulesetConfig(address(0), true, false);
|
|
619
628
|
|
|
620
629
|
// Empty 721 config — no tiers, so it tries to carry forward an existing hook.
|
|
621
|
-
// But no hook was stored for rulesetId=
|
|
630
|
+
// But no hook was stored for rulesetId=50 via this deployer.
|
|
622
631
|
JBOmnichain721Config memory empty721Config;
|
|
623
632
|
vm.prank(projectOwner);
|
|
624
633
|
vm.expectRevert(JBOmnichainDeployer.JBOmnichainDeployer_InvalidHook.selector);
|
package/test/TestAuditGaps.sol
CHANGED
|
@@ -539,6 +539,7 @@ contract TestAuditGaps is Test {
|
|
|
539
539
|
// latestRulesetIdOf still = BASE_TIME (from launch).
|
|
540
540
|
// Guard: BASE_TIME >= BASE_TIME + 1 -> false -> passes.
|
|
541
541
|
_mockLatestRulesetId(BASE_TIME);
|
|
542
|
+
_mockCurrentRulesetId(BASE_TIME);
|
|
542
543
|
|
|
543
544
|
uint256 expectedQueuedId = BASE_TIME + 1;
|
|
544
545
|
vm.mockCall(
|
|
@@ -565,6 +566,7 @@ contract TestAuditGaps is Test {
|
|
|
565
566
|
// Warp forward 1 second for first queue.
|
|
566
567
|
vm.warp(BASE_TIME + 1);
|
|
567
568
|
_mockLatestRulesetId(BASE_TIME);
|
|
569
|
+
_mockCurrentRulesetId(BASE_TIME);
|
|
568
570
|
|
|
569
571
|
uint256 firstQueueTime = BASE_TIME + 1;
|
|
570
572
|
vm.mockCall(
|
|
@@ -672,6 +674,7 @@ contract TestAuditGaps is Test {
|
|
|
672
674
|
// Warp past the latestRulesetId: block.timestamp = BASE_TIME + 3.
|
|
673
675
|
vm.warp(BASE_TIME + 3);
|
|
674
676
|
_mockLatestRulesetId(latestRulesetId);
|
|
677
|
+
_mockCurrentRulesetId(BASE_TIME);
|
|
675
678
|
|
|
676
679
|
uint256 expectedQueuedId = BASE_TIME + 3;
|
|
677
680
|
vm.mockCall(
|
|
@@ -699,6 +702,7 @@ contract TestAuditGaps is Test {
|
|
|
699
702
|
// Warp forward.
|
|
700
703
|
vm.warp(BASE_TIME + 100);
|
|
701
704
|
_mockLatestRulesetId(BASE_TIME);
|
|
705
|
+
_mockCurrentRulesetId(BASE_TIME);
|
|
702
706
|
|
|
703
707
|
uint256 expectedQueuedId = BASE_TIME + 100;
|
|
704
708
|
vm.mockCall(
|
|
@@ -739,6 +743,16 @@ contract TestAuditGaps is Test {
|
|
|
739
743
|
vm.warp(BASE_TIME + 50);
|
|
740
744
|
_mockLatestRulesetId(BASE_TIME);
|
|
741
745
|
|
|
746
|
+
// Mock currentOf to return a ruleset whose id matches the launch ruleset so carry-forward can look up the
|
|
747
|
+
// stored 721 hook.
|
|
748
|
+
JBRuleset memory currentRuleset;
|
|
749
|
+
currentRuleset.id = uint48(BASE_TIME);
|
|
750
|
+
vm.mockCall(
|
|
751
|
+
address(rulesetsContract),
|
|
752
|
+
abi.encodeWithSelector(IJBRulesets.currentOf.selector, projectId),
|
|
753
|
+
abi.encode(currentRuleset)
|
|
754
|
+
);
|
|
755
|
+
|
|
742
756
|
uint256 expectedQueuedId = BASE_TIME + 50;
|
|
743
757
|
vm.mockCall(
|
|
744
758
|
address(controller),
|
|
@@ -820,6 +834,7 @@ contract TestAuditGaps is Test {
|
|
|
820
834
|
|
|
821
835
|
vm.warp(BASE_TIME + 10);
|
|
822
836
|
_mockLatestRulesetId(BASE_TIME);
|
|
837
|
+
_mockCurrentRulesetId(BASE_TIME);
|
|
823
838
|
|
|
824
839
|
uint256 expectedQueuedId = BASE_TIME + 10;
|
|
825
840
|
vm.mockCall(
|
|
@@ -866,6 +881,14 @@ contract TestAuditGaps is Test {
|
|
|
866
881
|
);
|
|
867
882
|
}
|
|
868
883
|
|
|
884
|
+
function _mockCurrentRulesetId(uint256 currentRulesetId) internal {
|
|
885
|
+
JBRuleset memory r;
|
|
886
|
+
r.id = uint48(currentRulesetId);
|
|
887
|
+
vm.mockCall(
|
|
888
|
+
address(rulesetsContract), abi.encodeWithSelector(IJBRulesets.currentOf.selector, projectId), abi.encode(r)
|
|
889
|
+
);
|
|
890
|
+
}
|
|
891
|
+
|
|
869
892
|
function _makePayContext(uint256 pid, uint256 rid) internal returns (JBBeforePayRecordedContext memory) {
|
|
870
893
|
return JBBeforePayRecordedContext({
|
|
871
894
|
terminal: makeAddr("terminal"),
|
|
@@ -0,0 +1,305 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
pragma solidity 0.8.28;
|
|
3
|
+
|
|
4
|
+
import {TestBaseWorkflow} from "@bananapus/core-v6/test/helpers/TestBaseWorkflow.sol";
|
|
5
|
+
import {JBApprovalStatus} from "@bananapus/core-v6/src/enums/JBApprovalStatus.sol";
|
|
6
|
+
import {IJBController} from "@bananapus/core-v6/src/interfaces/IJBController.sol";
|
|
7
|
+
import {IJBDirectory} from "@bananapus/core-v6/src/interfaces/IJBDirectory.sol";
|
|
8
|
+
import {IJBPermissions} from "@bananapus/core-v6/src/interfaces/IJBPermissions.sol";
|
|
9
|
+
import {IJBProjects} from "@bananapus/core-v6/src/interfaces/IJBProjects.sol";
|
|
10
|
+
import {IJBRulesetApprovalHook} from "@bananapus/core-v6/src/interfaces/IJBRulesetApprovalHook.sol";
|
|
11
|
+
import {JBFundAccessLimitGroup} from "@bananapus/core-v6/src/structs/JBFundAccessLimitGroup.sol";
|
|
12
|
+
import {JBPermissionsData} from "@bananapus/core-v6/src/structs/JBPermissionsData.sol";
|
|
13
|
+
import {JBRuleset} from "@bananapus/core-v6/src/structs/JBRuleset.sol";
|
|
14
|
+
import {JBRulesetConfig} from "@bananapus/core-v6/src/structs/JBRulesetConfig.sol";
|
|
15
|
+
import {JBRulesetMetadata} from "@bananapus/core-v6/src/structs/JBRulesetMetadata.sol";
|
|
16
|
+
import {JBSplitGroup} from "@bananapus/core-v6/src/structs/JBSplitGroup.sol";
|
|
17
|
+
import {JBTerminalConfig} from "@bananapus/core-v6/src/structs/JBTerminalConfig.sol";
|
|
18
|
+
import {IJB721TiersHook} from "@bananapus/721-hook-v6/src/interfaces/IJB721TiersHook.sol";
|
|
19
|
+
import {IJB721TiersHookDeployer} from "@bananapus/721-hook-v6/src/interfaces/IJB721TiersHookDeployer.sol";
|
|
20
|
+
import {JBDeploy721TiersHookConfig} from "@bananapus/721-hook-v6/src/structs/JBDeploy721TiersHookConfig.sol";
|
|
21
|
+
import {JB721TierConfig} from "@bananapus/721-hook-v6/src/structs/JB721TierConfig.sol";
|
|
22
|
+
import {IJBSuckerRegistry} from "@bananapus/suckers-v6/src/interfaces/IJBSuckerRegistry.sol";
|
|
23
|
+
import {JBSuckerDeployerConfig} from "@bananapus/suckers-v6/src/structs/JBSuckerDeployerConfig.sol";
|
|
24
|
+
import {JBSuckersPair} from "@bananapus/suckers-v6/src/structs/JBSuckersPair.sol";
|
|
25
|
+
import {JBPermissionIds} from "@bananapus/permission-ids-v6/src/JBPermissionIds.sol";
|
|
26
|
+
import {ERC165} from "@openzeppelin/contracts/utils/introspection/ERC165.sol";
|
|
27
|
+
import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol";
|
|
28
|
+
import {JBOmnichainDeployer} from "../../src/JBOmnichainDeployer.sol";
|
|
29
|
+
import {JBOmnichain721Config} from "../../src/structs/JBOmnichain721Config.sol";
|
|
30
|
+
import {JBSuckerDeploymentConfig} from "../../src/structs/JBSuckerDeploymentConfig.sol";
|
|
31
|
+
|
|
32
|
+
contract RejectingApprovalHook is ERC165, IJBRulesetApprovalHook {
|
|
33
|
+
function DURATION() external pure override returns (uint256) {
|
|
34
|
+
return 0;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function approvalStatusOf(uint256, JBRuleset calldata) external pure override returns (JBApprovalStatus) {
|
|
38
|
+
return JBApprovalStatus.Failed;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function supportsInterface(bytes4 interfaceId) public view override(ERC165, IERC165) returns (bool) {
|
|
42
|
+
return interfaceId == type(IJBRulesetApprovalHook).interfaceId || super.supportsInterface(interfaceId);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
contract HookStub {
|
|
47
|
+
uint256 public lastProjectId;
|
|
48
|
+
|
|
49
|
+
function transferOwnershipToProject(uint256 projectId) external {
|
|
50
|
+
lastProjectId = projectId;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
contract SequentialHookDeployer is IJB721TiersHookDeployer {
|
|
55
|
+
HookStub[] internal _hooks;
|
|
56
|
+
uint256 internal _index;
|
|
57
|
+
|
|
58
|
+
constructor(HookStub[] memory hooks) {
|
|
59
|
+
_hooks = hooks;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function deployHookFor(
|
|
63
|
+
uint256,
|
|
64
|
+
JBDeploy721TiersHookConfig calldata,
|
|
65
|
+
bytes32
|
|
66
|
+
)
|
|
67
|
+
external
|
|
68
|
+
override
|
|
69
|
+
returns (IJB721TiersHook)
|
|
70
|
+
{
|
|
71
|
+
return IJB721TiersHook(address(_hooks[_index++]));
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
contract MockSuckerRegistryCarryForward is IJBSuckerRegistry {
|
|
76
|
+
function DIRECTORY() external pure override returns (IJBDirectory) {
|
|
77
|
+
return IJBDirectory(address(0));
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function PROJECTS() external pure override returns (IJBProjects) {
|
|
81
|
+
return IJBProjects(address(0));
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function isSuckerOf(uint256, address) external pure override returns (bool) {
|
|
85
|
+
return false;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function suckerDeployerIsAllowed(address) external pure override returns (bool) {
|
|
89
|
+
return false;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function suckerPairsOf(uint256) external pure override returns (JBSuckersPair[] memory) {
|
|
93
|
+
return new JBSuckersPair[](0);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function suckersOf(uint256) external pure override returns (address[] memory) {
|
|
97
|
+
return new address[](0);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function MAX_TO_REMOTE_FEE() external pure override returns (uint256) {
|
|
101
|
+
return 0;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function toRemoteFee() external pure override returns (uint256) {
|
|
105
|
+
return 0;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function setToRemoteFee(uint256) external override {}
|
|
109
|
+
function allowSuckerDeployer(address) external override {}
|
|
110
|
+
function allowSuckerDeployers(address[] calldata) external override {}
|
|
111
|
+
|
|
112
|
+
function deploySuckersFor(
|
|
113
|
+
uint256,
|
|
114
|
+
bytes32,
|
|
115
|
+
JBSuckerDeployerConfig[] memory
|
|
116
|
+
)
|
|
117
|
+
external
|
|
118
|
+
pure
|
|
119
|
+
override
|
|
120
|
+
returns (address[] memory)
|
|
121
|
+
{
|
|
122
|
+
return new address[](0);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
function removeDeprecatedSucker(uint256, address) external override {}
|
|
126
|
+
function removeSuckerDeployer(address) external override {}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
contract CarryForwardRejectedHookTest is TestBaseWorkflow {
|
|
130
|
+
JBOmnichainDeployer internal deployer;
|
|
131
|
+
RejectingApprovalHook internal rejectHook;
|
|
132
|
+
SequentialHookDeployer internal hookDeployer;
|
|
133
|
+
HookStub internal initialHook;
|
|
134
|
+
HookStub internal rejectedHook;
|
|
135
|
+
MockSuckerRegistryCarryForward internal suckerRegistry;
|
|
136
|
+
|
|
137
|
+
address internal owner;
|
|
138
|
+
|
|
139
|
+
function setUp() public override {
|
|
140
|
+
super.setUp();
|
|
141
|
+
|
|
142
|
+
owner = multisig();
|
|
143
|
+
rejectHook = new RejectingApprovalHook();
|
|
144
|
+
initialHook = new HookStub();
|
|
145
|
+
rejectedHook = new HookStub();
|
|
146
|
+
HookStub[] memory hooks = new HookStub[](2);
|
|
147
|
+
hooks[0] = initialHook;
|
|
148
|
+
hooks[1] = rejectedHook;
|
|
149
|
+
hookDeployer = new SequentialHookDeployer(hooks);
|
|
150
|
+
suckerRegistry = new MockSuckerRegistryCarryForward();
|
|
151
|
+
|
|
152
|
+
deployer = new JBOmnichainDeployer(
|
|
153
|
+
IJBSuckerRegistry(address(suckerRegistry)),
|
|
154
|
+
IJB721TiersHookDeployer(address(hookDeployer)),
|
|
155
|
+
IJBPermissions(address(jbPermissions())),
|
|
156
|
+
IJBProjects(address(jbProjects())),
|
|
157
|
+
trustedForwarder()
|
|
158
|
+
);
|
|
159
|
+
|
|
160
|
+
vm.prank(multisig());
|
|
161
|
+
jbDirectory().setIsAllowedToSetFirstController(address(deployer), true);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
function test_queueCarryForward_usesRejectedRulesetHook_notCurrentRulesetHook() public {
|
|
165
|
+
JBRulesetConfig[] memory initialRulesets = _makeRulesets(rejectHook);
|
|
166
|
+
JBTerminalConfig[] memory terminals = new JBTerminalConfig[](0);
|
|
167
|
+
JBOmnichain721Config memory configWithTiers = _configWithTiers(false);
|
|
168
|
+
|
|
169
|
+
(uint256 projectId, IJB721TiersHook launchedHook,) = deployer.launchProjectFor(
|
|
170
|
+
owner,
|
|
171
|
+
"ipfs://project",
|
|
172
|
+
configWithTiers,
|
|
173
|
+
initialRulesets,
|
|
174
|
+
terminals,
|
|
175
|
+
"launch",
|
|
176
|
+
_emptySuckerConfig(),
|
|
177
|
+
IJBController(address(jbController()))
|
|
178
|
+
);
|
|
179
|
+
uint256 initialRulesetId = jbRulesets().latestRulesetIdOf(projectId);
|
|
180
|
+
|
|
181
|
+
assertEq(address(launchedHook), address(initialHook), "launch should use the first hook");
|
|
182
|
+
|
|
183
|
+
_grantQueuePermissions(projectId);
|
|
184
|
+
|
|
185
|
+
vm.warp(block.timestamp + 1);
|
|
186
|
+
|
|
187
|
+
JBOmnichain721Config memory rejectedConfig = _configWithTiers(true);
|
|
188
|
+
(uint256 rejectedRulesetId,) = deployer.queueRulesetsOf(
|
|
189
|
+
projectId,
|
|
190
|
+
rejectedConfig,
|
|
191
|
+
_makeRulesets(IJBRulesetApprovalHook(address(0))),
|
|
192
|
+
"rejected",
|
|
193
|
+
IJBController(address(jbController()))
|
|
194
|
+
);
|
|
195
|
+
|
|
196
|
+
JBRuleset memory currentRuleset = jbRulesets().currentOf(projectId);
|
|
197
|
+
assertEq(currentRuleset.id, initialRulesetId, "core should still use the last approved ruleset");
|
|
198
|
+
|
|
199
|
+
vm.warp(block.timestamp + 2);
|
|
200
|
+
|
|
201
|
+
(uint256 carriedRulesetId,) = deployer.queueRulesetsOf(
|
|
202
|
+
projectId,
|
|
203
|
+
_default721Config(),
|
|
204
|
+
_makeRulesets(IJBRulesetApprovalHook(address(0))),
|
|
205
|
+
"carry",
|
|
206
|
+
IJBController(address(jbController()))
|
|
207
|
+
);
|
|
208
|
+
|
|
209
|
+
(IJB721TiersHook carriedHook, bool carriedCashOutFlag) = deployer.tiered721HookOf(projectId, carriedRulesetId);
|
|
210
|
+
(IJB721TiersHook currentHook, bool currentCashOutFlag) = deployer.tiered721HookOf(projectId, initialRulesetId);
|
|
211
|
+
(IJB721TiersHook rejectedStoredHook, bool rejectedCashOutFlag) =
|
|
212
|
+
deployer.tiered721HookOf(projectId, rejectedRulesetId);
|
|
213
|
+
|
|
214
|
+
assertEq(address(currentHook), address(initialHook), "approved ruleset should point to the initial hook");
|
|
215
|
+
assertFalse(currentCashOutFlag, "approved ruleset should preserve its original cash-out flag");
|
|
216
|
+
|
|
217
|
+
assertEq(address(rejectedStoredHook), address(rejectedHook), "rejected ruleset should store the second hook");
|
|
218
|
+
assertTrue(rejectedCashOutFlag, "rejected ruleset should store the second cash-out flag");
|
|
219
|
+
|
|
220
|
+
// The carry-forward uses currentOf (the approved ruleset), not the rejected queued one.
|
|
221
|
+
assertEq(
|
|
222
|
+
address(carriedHook),
|
|
223
|
+
address(initialHook),
|
|
224
|
+
"carry-forward should inherit the current (approved) hook, not the rejected one"
|
|
225
|
+
);
|
|
226
|
+
assertFalse(carriedCashOutFlag, "carry-forward should inherit the current (approved) cash-out flag");
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
function _configWithTiers(bool useDataHookForCashOut) internal pure returns (JBOmnichain721Config memory config) {
|
|
230
|
+
config = _default721Config();
|
|
231
|
+
config.useDataHookForCashOut = useDataHookForCashOut;
|
|
232
|
+
config.deployTiersHookConfig.tiersConfig.tiers = new JB721TierConfig[](1);
|
|
233
|
+
config.deployTiersHookConfig.tiersConfig.tiers[0].price = 1 ether;
|
|
234
|
+
config.deployTiersHookConfig.tiersConfig.tiers[0].initialSupply = 10;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
function _default721Config() internal pure returns (JBOmnichain721Config memory config) {
|
|
238
|
+
config.deployTiersHookConfig.tiersConfig.currency =
|
|
239
|
+
uint32(uint160(address(0x000000000000000000000000000000000000EEEe)));
|
|
240
|
+
config.deployTiersHookConfig.tiersConfig.decimals = 18;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
function _makeRulesets(IJBRulesetApprovalHook approvalHook)
|
|
244
|
+
internal
|
|
245
|
+
pure
|
|
246
|
+
returns (JBRulesetConfig[] memory configs)
|
|
247
|
+
{
|
|
248
|
+
configs = new JBRulesetConfig[](1);
|
|
249
|
+
configs[0] = JBRulesetConfig({
|
|
250
|
+
mustStartAtOrAfter: uint48(0),
|
|
251
|
+
duration: uint32(0),
|
|
252
|
+
weight: uint112(1e18),
|
|
253
|
+
weightCutPercent: uint32(0),
|
|
254
|
+
approvalHook: approvalHook,
|
|
255
|
+
metadata: JBRulesetMetadata({
|
|
256
|
+
reservedPercent: 0,
|
|
257
|
+
cashOutTaxRate: 0,
|
|
258
|
+
baseCurrency: uint32(uint160(address(0x000000000000000000000000000000000000EEEe))),
|
|
259
|
+
pausePay: false,
|
|
260
|
+
pauseCreditTransfers: false,
|
|
261
|
+
allowOwnerMinting: false,
|
|
262
|
+
allowSetCustomToken: false,
|
|
263
|
+
allowTerminalMigration: false,
|
|
264
|
+
allowSetController: false,
|
|
265
|
+
allowSetTerminals: false,
|
|
266
|
+
allowAddAccountingContext: false,
|
|
267
|
+
allowAddPriceFeed: false,
|
|
268
|
+
ownerMustSendPayouts: false,
|
|
269
|
+
holdFees: false,
|
|
270
|
+
useTotalSurplusForCashOuts: false,
|
|
271
|
+
useDataHookForPay: false,
|
|
272
|
+
useDataHookForCashOut: false,
|
|
273
|
+
dataHook: address(0),
|
|
274
|
+
metadata: 0
|
|
275
|
+
}),
|
|
276
|
+
splitGroups: new JBSplitGroup[](0),
|
|
277
|
+
fundAccessLimitGroups: new JBFundAccessLimitGroup[](0)
|
|
278
|
+
});
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
function _emptySuckerConfig() internal pure returns (JBSuckerDeploymentConfig memory) {
|
|
282
|
+
return JBSuckerDeploymentConfig({deployerConfigurations: new JBSuckerDeployerConfig[](0), salt: bytes32(0)});
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
function _grantQueuePermissions(uint256 projectId) internal {
|
|
286
|
+
uint8[] memory permissionIds = new uint8[](1);
|
|
287
|
+
permissionIds[0] = JBPermissionIds.QUEUE_RULESETS;
|
|
288
|
+
|
|
289
|
+
vm.prank(owner);
|
|
290
|
+
jbPermissions()
|
|
291
|
+
.setPermissionsFor(
|
|
292
|
+
owner,
|
|
293
|
+
JBPermissionsData({operator: address(this), projectId: uint64(projectId), permissionIds: permissionIds})
|
|
294
|
+
);
|
|
295
|
+
|
|
296
|
+
vm.prank(owner);
|
|
297
|
+
jbPermissions()
|
|
298
|
+
.setPermissionsFor(
|
|
299
|
+
owner,
|
|
300
|
+
JBPermissionsData({
|
|
301
|
+
operator: address(deployer), projectId: uint64(projectId), permissionIds: permissionIds
|
|
302
|
+
})
|
|
303
|
+
);
|
|
304
|
+
}
|
|
305
|
+
}
|
|
@@ -11,6 +11,7 @@ import {IJBProjects} from "@bananapus/core-v6/src/interfaces/IJBProjects.sol";
|
|
|
11
11
|
import {IJBRulesetDataHook} from "@bananapus/core-v6/src/interfaces/IJBRulesetDataHook.sol";
|
|
12
12
|
import {IJBRulesets} from "@bananapus/core-v6/src/interfaces/IJBRulesets.sol";
|
|
13
13
|
import {JBConstants} from "@bananapus/core-v6/src/libraries/JBConstants.sol";
|
|
14
|
+
import {JBRuleset} from "@bananapus/core-v6/src/structs/JBRuleset.sol";
|
|
14
15
|
import {JBBeforeCashOutRecordedContext} from "@bananapus/core-v6/src/structs/JBBeforeCashOutRecordedContext.sol";
|
|
15
16
|
import {JBCashOutHookSpecification} from "@bananapus/core-v6/src/structs/JBCashOutHookSpecification.sol";
|
|
16
17
|
import {JBFundAccessLimitGroup} from "@bananapus/core-v6/src/structs/JBFundAccessLimitGroup.sol";
|
|
@@ -196,6 +197,15 @@ contract JBOmnichainDeployerTest is Test {
|
|
|
196
197
|
abi.encode(initialRulesetId)
|
|
197
198
|
);
|
|
198
199
|
|
|
200
|
+
// Mock currentOf to return a JBRuleset with id = initialRulesetId so the carry-forward lookup succeeds.
|
|
201
|
+
JBRuleset memory currentRuleset;
|
|
202
|
+
currentRuleset.id = uint48(initialRulesetId);
|
|
203
|
+
vm.mockCall(
|
|
204
|
+
address(rulesets),
|
|
205
|
+
abi.encodeWithSelector(IJBRulesets.currentOf.selector, PROJECT_ID),
|
|
206
|
+
abi.encode(currentRuleset)
|
|
207
|
+
);
|
|
208
|
+
|
|
199
209
|
vm.warp(block.timestamp + 1);
|
|
200
210
|
uint256 queuedRulesetId = block.timestamp;
|
|
201
211
|
vm.mockCall(
|
|
@@ -34,6 +34,7 @@ import {IJB721TokenUriResolver} from "@bananapus/721-hook-v6/src/interfaces/IJB7
|
|
|
34
34
|
import {JBDeploy721TiersHookConfig} from "@bananapus/721-hook-v6/src/structs/JBDeploy721TiersHookConfig.sol";
|
|
35
35
|
import {JB721TierConfig} from "@bananapus/721-hook-v6/src/structs/JB721TierConfig.sol";
|
|
36
36
|
import {JB721InitTiersConfig} from "@bananapus/721-hook-v6/src/structs/JB721InitTiersConfig.sol";
|
|
37
|
+
import {JB721TierConfigFlags} from "@bananapus/721-hook-v6/src/structs/JB721TierConfigFlags.sol";
|
|
37
38
|
import {JB721TiersHookFlags} from "@bananapus/721-hook-v6/src/structs/JB721TiersHookFlags.sol";
|
|
38
39
|
import {JBAddressRegistry} from "@bananapus/address-registry-v6/src/JBAddressRegistry.sol";
|
|
39
40
|
import {IJBAddressRegistry} from "@bananapus/address-registry-v6/src/interfaces/IJBAddressRegistry.sol";
|
|
@@ -231,13 +232,15 @@ abstract contract OmnichainForkTestBase is TestBaseWorkflow {
|
|
|
231
232
|
encodedIPFSUri: bytes32("tier1"),
|
|
232
233
|
category: 1,
|
|
233
234
|
discountPercent: 0,
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
235
|
+
flags: JB721TierConfigFlags({
|
|
236
|
+
allowOwnerMint: false,
|
|
237
|
+
useReserveBeneficiaryAsDefault: false,
|
|
238
|
+
transfersPausable: false,
|
|
239
|
+
useVotingUnits: false,
|
|
240
|
+
cantBeRemoved: false,
|
|
241
|
+
cantIncreaseDiscountPercent: false,
|
|
242
|
+
cantBuyWithCredits: false
|
|
243
|
+
}),
|
|
241
244
|
splitPercent: SPLIT_PERCENT,
|
|
242
245
|
splits: tierSplits
|
|
243
246
|
});
|
|
@@ -9,6 +9,7 @@ import {JBRulesetConfig} from "@bananapus/core-v6/src/structs/JBRulesetConfig.so
|
|
|
9
9
|
import {JBSplit} from "@bananapus/core-v6/src/structs/JBSplit.sol";
|
|
10
10
|
import {IJB721TiersHook} from "@bananapus/721-hook-v6/src/interfaces/IJB721TiersHook.sol";
|
|
11
11
|
import {JB721TierConfig} from "@bananapus/721-hook-v6/src/structs/JB721TierConfig.sol";
|
|
12
|
+
import {JB721TierConfigFlags} from "@bananapus/721-hook-v6/src/structs/JB721TierConfigFlags.sol";
|
|
12
13
|
import {IJBOwnable} from "@bananapus/ownable-v6/src/interfaces/IJBOwnable.sol";
|
|
13
14
|
import {JBPermissionIds} from "@bananapus/permission-ids-v6/src/JBPermissionIds.sol";
|
|
14
15
|
import {JBOmnichain721Config} from "../../src/structs/JBOmnichain721Config.sol";
|
|
@@ -69,13 +70,15 @@ contract TestOmnichain721QueueAndAdjust is OmnichainForkTestBase {
|
|
|
69
70
|
encodedIPFSUri: bytes32("tier2"),
|
|
70
71
|
category: 2,
|
|
71
72
|
discountPercent: 0,
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
73
|
+
flags: JB721TierConfigFlags({
|
|
74
|
+
allowOwnerMint: false,
|
|
75
|
+
useReserveBeneficiaryAsDefault: false,
|
|
76
|
+
transfersPausable: false,
|
|
77
|
+
useVotingUnits: false,
|
|
78
|
+
cantBeRemoved: false,
|
|
79
|
+
cantIncreaseDiscountPercent: false,
|
|
80
|
+
cantBuyWithCredits: false
|
|
81
|
+
}),
|
|
79
82
|
splitPercent: 0,
|
|
80
83
|
splits: new JBSplit[](0)
|
|
81
84
|
});
|
|
@@ -146,13 +149,15 @@ contract TestOmnichain721QueueAndAdjust is OmnichainForkTestBase {
|
|
|
146
149
|
encodedIPFSUri: bytes32("tier3"),
|
|
147
150
|
category: 3,
|
|
148
151
|
discountPercent: 0,
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
152
|
+
flags: JB721TierConfigFlags({
|
|
153
|
+
allowOwnerMint: false,
|
|
154
|
+
useReserveBeneficiaryAsDefault: false,
|
|
155
|
+
transfersPausable: false,
|
|
156
|
+
useVotingUnits: false,
|
|
157
|
+
cantBeRemoved: false,
|
|
158
|
+
cantIncreaseDiscountPercent: false,
|
|
159
|
+
cantBuyWithCredits: false
|
|
160
|
+
}),
|
|
156
161
|
splitPercent: 0,
|
|
157
162
|
splits: new JBSplit[](0)
|
|
158
163
|
});
|
|
@@ -195,13 +200,15 @@ contract TestOmnichain721QueueAndAdjust is OmnichainForkTestBase {
|
|
|
195
200
|
encodedIPFSUri: bytes32("bad"),
|
|
196
201
|
category: 4,
|
|
197
202
|
discountPercent: 0,
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
203
|
+
flags: JB721TierConfigFlags({
|
|
204
|
+
allowOwnerMint: false,
|
|
205
|
+
useReserveBeneficiaryAsDefault: false,
|
|
206
|
+
transfersPausable: false,
|
|
207
|
+
useVotingUnits: false,
|
|
208
|
+
cantBeRemoved: false,
|
|
209
|
+
cantIncreaseDiscountPercent: false,
|
|
210
|
+
cantBuyWithCredits: false
|
|
211
|
+
}),
|
|
205
212
|
splitPercent: 0,
|
|
206
213
|
splits: new JBSplit[](0)
|
|
207
214
|
});
|