@bananapus/721-hook-v6 0.0.41 → 0.0.43
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/foundry.lock +1 -7
- package/foundry.toml +1 -1
- package/package.json +20 -9
- package/script/Deploy.s.sol +2 -2
- package/src/JB721Checkpoints.sol +60 -18
- package/src/JB721CheckpointsDeployer.sol +10 -5
- package/src/JB721TiersHook.sol +4 -1
- package/src/JB721TiersHookProjectDeployer.sol +68 -30
- package/src/JB721TiersHookStore.sol +1 -4
- package/src/interfaces/IJB721Checkpoints.sol +21 -14
- package/src/interfaces/IJB721CheckpointsDeployer.sol +6 -2
- package/src/interfaces/IJB721TiersHookProjectDeployer.sol +2 -0
- package/test/utils/AccessJBLib.sol +49 -0
- package/test/utils/ForTest_JB721TiersHook.sol +246 -0
- package/test/utils/TestBaseWorkflow.sol +213 -0
- package/test/utils/UnitTestSetup.sol +805 -0
- package/.gas-snapshot +0 -152
- package/ADMINISTRATION.md +0 -87
- package/ARCHITECTURE.md +0 -98
- package/AUDIT_INSTRUCTIONS.md +0 -77
- package/RISKS.md +0 -118
- package/SKILLS.md +0 -43
- package/STYLE_GUIDE.md +0 -610
- package/USER_JOURNEYS.md +0 -121
- package/assets/findings/nana-721-hook-v6-pashov-ai-audit-report-20260330-091257.md +0 -83
- package/slither-ci.config.json +0 -10
- package/test/721HookAttacks.t.sol +0 -408
- package/test/E2E/Pay_Mint_Redeem_E2E.t.sol +0 -985
- package/test/Fork.t.sol +0 -2346
- package/test/TestAuditGaps.sol +0 -1075
- package/test/TestCheckpoints.t.sol +0 -341
- package/test/TestSafeTransferReentrancy.t.sol +0 -305
- package/test/TestVotingUnitsLifecycle.t.sol +0 -313
- package/test/audit/AuditRegressions.t.sol +0 -83
- package/test/audit/CrossCurrencySplitNoPrices.t.sol +0 -123
- package/test/audit/FreshAudit.t.sol +0 -197
- package/test/audit/FutureTierPoC.t.sol +0 -39
- package/test/audit/FutureTierRemoval.t.sol +0 -47
- package/test/audit/Pass12L18.t.sol +0 -80
- package/test/audit/PayCreditsBypassTierSplits.t.sol +0 -200
- package/test/audit/ProjectDeployerAuth.t.sol +0 -266
- package/test/audit/RepoFindings.t.sol +0 -195
- package/test/audit/ReserveActivation.t.sol +0 -87
- package/test/audit/RetroactiveReserveBeneficiaryDilution.t.sol +0 -149
- package/test/audit/SameCurrencyDecimalMismatch.t.sol +0 -249
- package/test/audit/SplitCreditsMismatch.t.sol +0 -219
- package/test/audit/SplitFailureRedistribution.t.sol +0 -143
- package/test/audit/USDTVoidReturnCompat.t.sol +0 -301
- package/test/fork/ERC20CashOutFork.t.sol +0 -633
- package/test/fork/ERC20TierSplitFork.t.sol +0 -596
- package/test/fork/IssueTokensForSplitsFork.t.sol +0 -516
- package/test/invariants/TierLifecycleInvariant.t.sol +0 -188
- package/test/invariants/TieredHookStoreInvariant.t.sol +0 -86
- package/test/invariants/handlers/TierLifecycleHandler.sol +0 -300
- package/test/invariants/handlers/TierStoreHandler.sol +0 -165
- package/test/regression/BrokenTerminalDoesNotDos.t.sol +0 -277
- package/test/regression/CacheTierLookup.t.sol +0 -190
- package/test/regression/ProjectDeployerRulesets.t.sol +0 -358
- package/test/regression/ReserveBeneficiaryOverwrite.t.sol +0 -155
- package/test/regression/SplitDistributionBugs.t.sol +0 -751
- package/test/regression/SplitNoBeneficiary.t.sol +0 -140
- package/test/unit/AuditFixes_Unit.t.sol +0 -624
- package/test/unit/JB721CheckpointsDeployer_AccessControl.t.sol +0 -116
- package/test/unit/JB721TiersRulesetMetadataResolver.t.sol +0 -144
- package/test/unit/JBBitmap.t.sol +0 -170
- package/test/unit/JBIpfsDecoder.t.sol +0 -136
- package/test/unit/TierSupplyReserveCheck.t.sol +0 -221
- package/test/unit/adjustTier_Unit.t.sol +0 -1942
- package/test/unit/deployer_Unit.t.sol +0 -114
- package/test/unit/getters_constructor_Unit.t.sol +0 -593
- package/test/unit/mintFor_mintReservesFor_Unit.t.sol +0 -452
- package/test/unit/pay_CrossCurrency_Unit.t.sol +0 -530
- package/test/unit/pay_Unit.t.sol +0 -1661
- package/test/unit/redeem_Unit.t.sol +0 -473
- package/test/unit/relayBeneficiary_Unit.t.sol +0 -182
- package/test/unit/splitHookDistribution_Unit.t.sol +0 -604
- package/test/unit/tierSplitRouting_Unit.t.sol +0 -757
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
pragma solidity 0.8.28;
|
|
3
|
+
|
|
4
|
+
// forge-lint: disable-next-line(unaliased-plain-import)
|
|
5
|
+
import "@bananapus/core-v6/src/libraries/JBCurrencyIds.sol";
|
|
6
|
+
// forge-lint: disable-next-line(unaliased-plain-import)
|
|
7
|
+
import "@bananapus/core-v6/src/libraries/JBConstants.sol";
|
|
8
|
+
|
|
9
|
+
contract AccessJBLib {
|
|
10
|
+
// forge-lint: disable-next-line(mixed-case-function)
|
|
11
|
+
function NATIVE() external pure returns (uint256) {
|
|
12
|
+
return uint32(uint160(JBConstants.NATIVE_TOKEN));
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
// forge-lint: disable-next-line(mixed-case-function)
|
|
16
|
+
function USD() external pure returns (uint256) {
|
|
17
|
+
return JBCurrencyIds.USD;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// forge-lint: disable-next-line(mixed-case-function)
|
|
21
|
+
function NATIVE_TOKEN() external pure returns (address) {
|
|
22
|
+
return JBConstants.NATIVE_TOKEN;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// forge-lint: disable-next-line(mixed-case-function)
|
|
26
|
+
function MAX_FEE() external pure returns (uint256) {
|
|
27
|
+
return JBConstants.MAX_FEE;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// forge-lint: disable-next-line(mixed-case-function)
|
|
31
|
+
function MAX_RESERVED_PERCENT() external pure returns (uint256) {
|
|
32
|
+
return JBConstants.MAX_RESERVED_PERCENT;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// forge-lint: disable-next-line(mixed-case-function)
|
|
36
|
+
function MAX_CASH_OUT_TAX_RATE() external pure returns (uint256) {
|
|
37
|
+
return JBConstants.MAX_CASH_OUT_TAX_RATE;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// forge-lint: disable-next-line(mixed-case-function)
|
|
41
|
+
function MAX_WEIGHT_CUT_PERCENT() external pure returns (uint256) {
|
|
42
|
+
return JBConstants.MAX_WEIGHT_CUT_PERCENT;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// forge-lint: disable-next-line(mixed-case-function)
|
|
46
|
+
function SPLITS_TOTAL_PERCENT() external pure returns (uint256) {
|
|
47
|
+
return JBConstants.SPLITS_TOTAL_PERCENT;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
pragma solidity 0.8.28;
|
|
3
|
+
|
|
4
|
+
// forge-lint: disable-next-line(unaliased-plain-import)
|
|
5
|
+
import "../../src/interfaces/IJB721TiersHook.sol";
|
|
6
|
+
import {JB721TierFlags} from "../../src/structs/JB721TierFlags.sol";
|
|
7
|
+
|
|
8
|
+
// forge-lint: disable-next-line(unaliased-plain-import)
|
|
9
|
+
import "../../src/JB721TiersHook.sol";
|
|
10
|
+
// forge-lint: disable-next-line(unaliased-plain-import)
|
|
11
|
+
import "../../src/JB721TiersHookStore.sol";
|
|
12
|
+
|
|
13
|
+
import {JB721CheckpointsDeployer} from "../../src/JB721CheckpointsDeployer.sol";
|
|
14
|
+
import {IJB721CheckpointsDeployer} from "../../src/interfaces/IJB721CheckpointsDeployer.sol";
|
|
15
|
+
|
|
16
|
+
// forge-lint: disable-next-line(unaliased-plain-import)
|
|
17
|
+
import "../../src/structs/JBBitmapWord.sol";
|
|
18
|
+
|
|
19
|
+
// forge-lint: disable-next-line(unaliased-plain-import)
|
|
20
|
+
import "@bananapus/core-v6/src/structs/JBRulesetMetadata.sol";
|
|
21
|
+
// forge-lint: disable-next-line(unaliased-plain-import)
|
|
22
|
+
import "@bananapus/core-v6/src/interfaces/IJBPermissioned.sol";
|
|
23
|
+
import {MetadataResolverHelper} from "@bananapus/core-v6/test/helpers/MetadataResolverHelper.sol";
|
|
24
|
+
|
|
25
|
+
// forge-lint: disable-next-line(unaliased-plain-import)
|
|
26
|
+
import "@bananapus/core-v6/src/libraries/JBConstants.sol";
|
|
27
|
+
|
|
28
|
+
// forge-lint: disable-next-line(unaliased-plain-import)
|
|
29
|
+
import "./UnitTestSetup.sol"; // Only used to get the `PAY_HOOK_ID` and `CASH_OUT_HOOK_ID` constants.
|
|
30
|
+
|
|
31
|
+
interface IJB721TiersHookStore_ForTest is IJB721TiersHookStore {
|
|
32
|
+
// forge-lint: disable-next-line(mixed-case-function)
|
|
33
|
+
function ForTest_dumpTiersList(address nft) external view returns (JB721Tier[] memory tiers);
|
|
34
|
+
// forge-lint: disable-next-line(mixed-case-function)
|
|
35
|
+
function ForTest_setTier(address hook, uint256 index, JBStored721Tier calldata newTier) external;
|
|
36
|
+
// forge-lint: disable-next-line(mixed-case-function)
|
|
37
|
+
function ForTest_setTierVotingUnits(address hook, uint256 tierId, uint32 votingUnits) external;
|
|
38
|
+
// forge-lint: disable-next-line(mixed-case-function)
|
|
39
|
+
function ForTest_setBalanceOf(address hook, address holder, uint256 tier, uint256 balance) external;
|
|
40
|
+
// forge-lint: disable-next-line(mixed-case-function)
|
|
41
|
+
function ForTest_setReservesMintedFor(address hook, uint256 tier, uint256 amount) external;
|
|
42
|
+
// forge-lint: disable-next-line(mixed-case-function)
|
|
43
|
+
function ForTest_setIsTierRemoved(address hook, uint256 tokenId) external;
|
|
44
|
+
// forge-lint: disable-next-line(mixed-case-function)
|
|
45
|
+
function ForTest_packBools(
|
|
46
|
+
bool allowOwnerMint,
|
|
47
|
+
bool transfersPausable,
|
|
48
|
+
bool useVotingUnits,
|
|
49
|
+
bool cantBeRemoved,
|
|
50
|
+
bool cantIncreaseDiscountPercent,
|
|
51
|
+
bool cantBuyWithCredits
|
|
52
|
+
)
|
|
53
|
+
external
|
|
54
|
+
returns (uint8);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// A customized 721 tiers hook for testing purposes.
|
|
58
|
+
contract ForTest_JB721TiersHook is JB721TiersHook {
|
|
59
|
+
// forge-lint: disable-next-line(mixed-case-variable)
|
|
60
|
+
IJB721TiersHookStore_ForTest public test_store;
|
|
61
|
+
MetadataResolverHelper metadataHelper;
|
|
62
|
+
|
|
63
|
+
uint256 constant SURPLUS = 10e18;
|
|
64
|
+
uint256 constant CASH_OUT_TAX_RATE = JBConstants.MAX_CASH_OUT_TAX_RATE; // 40%
|
|
65
|
+
address _trustedForwarder = address(123_456);
|
|
66
|
+
|
|
67
|
+
/// @dev Bundles ForTest_JB721TiersHook constructor args to avoid stack-too-deep.
|
|
68
|
+
struct ForTestInitConfig {
|
|
69
|
+
uint256 projectId;
|
|
70
|
+
string name;
|
|
71
|
+
string symbol;
|
|
72
|
+
string baseUri;
|
|
73
|
+
IJB721TokenUriResolver tokenUriResolver;
|
|
74
|
+
string contractUri;
|
|
75
|
+
JB721TierConfig[] tiers;
|
|
76
|
+
JB721TiersHookFlags flags;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
constructor(
|
|
80
|
+
ForTestInitConfig memory config,
|
|
81
|
+
IJBDirectory directory,
|
|
82
|
+
IJBPrices prices,
|
|
83
|
+
IJBRulesets rulesets,
|
|
84
|
+
IJB721TiersHookStore store,
|
|
85
|
+
IJBSplits splits
|
|
86
|
+
)
|
|
87
|
+
// The directory is also `IJBPermissioned`.
|
|
88
|
+
JB721TiersHook(
|
|
89
|
+
directory,
|
|
90
|
+
IJBPermissioned(address(directory)).PERMISSIONS(),
|
|
91
|
+
prices,
|
|
92
|
+
rulesets,
|
|
93
|
+
store,
|
|
94
|
+
splits,
|
|
95
|
+
IJB721CheckpointsDeployer(address(new JB721CheckpointsDeployer(store))),
|
|
96
|
+
_trustedForwarder
|
|
97
|
+
)
|
|
98
|
+
{
|
|
99
|
+
// Reset the _initialized flag set by the parent constructor so this test contract can initialize itself.
|
|
100
|
+
_initialized = false;
|
|
101
|
+
JB721TiersHook.initialize(
|
|
102
|
+
config.projectId,
|
|
103
|
+
config.name,
|
|
104
|
+
config.symbol,
|
|
105
|
+
config.baseUri,
|
|
106
|
+
config.tokenUriResolver,
|
|
107
|
+
config.contractUri,
|
|
108
|
+
JB721InitTiersConfig({
|
|
109
|
+
tiers: config.tiers, currency: uint32(uint160(JBConstants.NATIVE_TOKEN)), decimals: 18
|
|
110
|
+
}),
|
|
111
|
+
config.flags
|
|
112
|
+
);
|
|
113
|
+
test_store = IJB721TiersHookStore_ForTest(address(store));
|
|
114
|
+
|
|
115
|
+
metadataHelper = new MetadataResolverHelper();
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// forge-lint: disable-next-line(mixed-case-function)
|
|
119
|
+
function ForTest_setOwnerOf(uint256 tokenId, address owner) public {
|
|
120
|
+
_owners[tokenId] = owner;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function burn(uint256[] memory tokenIds) public {
|
|
124
|
+
for (uint256 i; i < tokenIds.length; i++) {
|
|
125
|
+
_burn(tokenIds[i]);
|
|
126
|
+
}
|
|
127
|
+
STORE.recordBurn(tokenIds);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// A customized 721 tiers hook store for testing purposes.
|
|
132
|
+
contract ForTest_JB721TiersHookStore is JB721TiersHookStore, IJB721TiersHookStore_ForTest {
|
|
133
|
+
using JBBitmap for mapping(uint256 => uint256);
|
|
134
|
+
using JBBitmap for JBBitmapWord;
|
|
135
|
+
|
|
136
|
+
// forge-lint: disable-next-line(mixed-case-function)
|
|
137
|
+
function ForTest_dumpTiersList(address nft) public view override returns (JB721Tier[] memory tiers) {
|
|
138
|
+
// Keep a reference to the max tier ID.
|
|
139
|
+
uint256 maxTierId = maxTierIdOf[nft];
|
|
140
|
+
// Initialize an array with the appropriate length.
|
|
141
|
+
tiers = new JB721Tier[](maxTierId);
|
|
142
|
+
// Count the number of included tiers.
|
|
143
|
+
uint256 numberOfIncludedTiers;
|
|
144
|
+
// Get a reference to the sorted index being iterated on, starting with the first one.
|
|
145
|
+
uint256 currentSortIndex = _firstSortedTierIdOf(nft, 0);
|
|
146
|
+
// Keep a reference to the tier being iterated on.
|
|
147
|
+
JBStored721Tier memory storedTier;
|
|
148
|
+
// Make the sorted array.
|
|
149
|
+
while (currentSortIndex != 0 && numberOfIncludedTiers < maxTierId) {
|
|
150
|
+
storedTier = _storedTierOf[nft][currentSortIndex];
|
|
151
|
+
|
|
152
|
+
// Unpack stored tier.
|
|
153
|
+
(bool allowOwnerMint, bool transfersPausable,,,,) = _unpackBools(storedTier.packedBools);
|
|
154
|
+
|
|
155
|
+
// Add the tier to the array being returned.
|
|
156
|
+
tiers[numberOfIncludedTiers++] = JB721Tier({
|
|
157
|
+
// forge-lint: disable-next-line(unsafe-typecast)
|
|
158
|
+
id: uint32(currentSortIndex),
|
|
159
|
+
price: storedTier.price,
|
|
160
|
+
remainingSupply: storedTier.remainingSupply,
|
|
161
|
+
initialSupply: storedTier.initialSupply,
|
|
162
|
+
votingUnits: storedTier.price,
|
|
163
|
+
reserveFrequency: storedTier.reserveFrequency,
|
|
164
|
+
reserveBeneficiary: reserveBeneficiaryOf(nft, currentSortIndex),
|
|
165
|
+
encodedIPFSUri: encodedIPFSUriOf[nft][currentSortIndex],
|
|
166
|
+
category: storedTier.category,
|
|
167
|
+
discountPercent: storedTier.discountPercent,
|
|
168
|
+
flags: JB721TierFlags({
|
|
169
|
+
allowOwnerMint: allowOwnerMint,
|
|
170
|
+
transfersPausable: transfersPausable,
|
|
171
|
+
cantBeRemoved: false,
|
|
172
|
+
cantIncreaseDiscountPercent: false,
|
|
173
|
+
cantBuyWithCredits: false
|
|
174
|
+
}),
|
|
175
|
+
splitPercent: storedTier.splitPercent,
|
|
176
|
+
resolvedUri: ""
|
|
177
|
+
});
|
|
178
|
+
// Set the next sort index.
|
|
179
|
+
currentSortIndex = _nextSortedTierIdOf(nft, currentSortIndex, maxTierId);
|
|
180
|
+
}
|
|
181
|
+
// Drop the empty tiers at the end of the array.
|
|
182
|
+
// The array's size is based on `maxTierIdOf`, which *might* exceed the actual number of tiers.
|
|
183
|
+
for (uint256 i = tiers.length - 1; i >= 0; i--) {
|
|
184
|
+
if (tiers[i].id == 0) {
|
|
185
|
+
assembly ("memory-safe") {
|
|
186
|
+
mstore(tiers, sub(mload(tiers), 1))
|
|
187
|
+
}
|
|
188
|
+
} else {
|
|
189
|
+
break;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// forge-lint: disable-next-line(mixed-case-function)
|
|
195
|
+
function ForTest_setTier(address hook, uint256 index, JBStored721Tier calldata newTier) public override {
|
|
196
|
+
_storedTierOf[address(hook)][index] = newTier;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
// forge-lint: disable-next-line(mixed-case-function)
|
|
200
|
+
function ForTest_setTierVotingUnits(address hook, uint256 tierId, uint32 votingUnits) public override {
|
|
201
|
+
_tierVotingUnitsOf[address(hook)][tierId] = votingUnits;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// forge-lint: disable-next-line(mixed-case-function)
|
|
205
|
+
function ForTest_setBalanceOf(address hook, address holder, uint256 tier, uint256 balance) public override {
|
|
206
|
+
tierBalanceOf[address(hook)][holder][tier] = balance;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
// forge-lint: disable-next-line(mixed-case-function)
|
|
210
|
+
function ForTest_setReservesMintedFor(address hook, uint256 tier, uint256 amount) public override {
|
|
211
|
+
numberOfReservesMintedFor[address(hook)][tier] = amount;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
// forge-lint: disable-next-line(mixed-case-function)
|
|
215
|
+
function ForTest_setIsTierRemoved(address hook, uint256 tokenId) public override {
|
|
216
|
+
_removedTiersBitmapWordOf[hook].removeTier(tokenId);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
// forge-lint: disable-next-line(mixed-case-function)
|
|
220
|
+
function ForTest_packBools(
|
|
221
|
+
bool allowOwnerMint,
|
|
222
|
+
bool transfersPausable,
|
|
223
|
+
bool useVotingUnits,
|
|
224
|
+
bool cantBeRemoved,
|
|
225
|
+
bool cantIncreaseDiscountPercent,
|
|
226
|
+
bool cantBuyWithCredits
|
|
227
|
+
)
|
|
228
|
+
public
|
|
229
|
+
pure
|
|
230
|
+
returns (uint8)
|
|
231
|
+
{
|
|
232
|
+
return _packBools(
|
|
233
|
+
allowOwnerMint,
|
|
234
|
+
transfersPausable,
|
|
235
|
+
useVotingUnits,
|
|
236
|
+
cantBeRemoved,
|
|
237
|
+
cantIncreaseDiscountPercent,
|
|
238
|
+
cantBuyWithCredits
|
|
239
|
+
);
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
// forge-lint: disable-next-line(mixed-case-function)
|
|
243
|
+
function ForTest_unpackBools(uint8 packed) public pure returns (bool, bool, bool, bool, bool, bool) {
|
|
244
|
+
return _unpackBools(packed);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
pragma solidity 0.8.28;
|
|
3
|
+
|
|
4
|
+
// forge-lint: disable-next-line(unaliased-plain-import)
|
|
5
|
+
import "@bananapus/core-v6/src/JBController.sol";
|
|
6
|
+
// forge-lint: disable-next-line(unaliased-plain-import)
|
|
7
|
+
import "@bananapus/core-v6/src/JBDirectory.sol";
|
|
8
|
+
// forge-lint: disable-next-line(unaliased-plain-import)
|
|
9
|
+
import "@bananapus/core-v6/src/JBMultiTerminal.sol";
|
|
10
|
+
// forge-lint: disable-next-line(unaliased-plain-import)
|
|
11
|
+
import "@bananapus/core-v6/src/JBFundAccessLimits.sol";
|
|
12
|
+
// forge-lint: disable-next-line(unaliased-plain-import)
|
|
13
|
+
import "@bananapus/core-v6/src/JBFeelessAddresses.sol";
|
|
14
|
+
// forge-lint: disable-next-line(unaliased-plain-import)
|
|
15
|
+
import "@bananapus/core-v6/src/JBTerminalStore.sol";
|
|
16
|
+
// forge-lint: disable-next-line(unaliased-plain-import)
|
|
17
|
+
import "@bananapus/core-v6/src/JBRulesets.sol";
|
|
18
|
+
// forge-lint: disable-next-line(unaliased-plain-import)
|
|
19
|
+
import "@bananapus/core-v6/src/JBPermissions.sol";
|
|
20
|
+
// forge-lint: disable-next-line(unaliased-plain-import)
|
|
21
|
+
import "@bananapus/core-v6/src/JBPrices.sol";
|
|
22
|
+
import {JBProjects} from "@bananapus/core-v6/src/JBProjects.sol";
|
|
23
|
+
// forge-lint: disable-next-line(unaliased-plain-import)
|
|
24
|
+
import "@bananapus/core-v6/src/JBSplits.sol";
|
|
25
|
+
// forge-lint: disable-next-line(unaliased-plain-import)
|
|
26
|
+
import "@bananapus/core-v6/src/JBERC20.sol";
|
|
27
|
+
// forge-lint: disable-next-line(unaliased-plain-import)
|
|
28
|
+
import "@bananapus/core-v6/src/JBTokens.sol";
|
|
29
|
+
|
|
30
|
+
// forge-lint: disable-next-line(unaliased-plain-import)
|
|
31
|
+
import "@bananapus/core-v6/src/structs/JBAfterPayRecordedContext.sol";
|
|
32
|
+
// forge-lint: disable-next-line(unaliased-plain-import)
|
|
33
|
+
import "@bananapus/core-v6/src/structs/JBAfterCashOutRecordedContext.sol";
|
|
34
|
+
// forge-lint: disable-next-line(unaliased-plain-import)
|
|
35
|
+
import "@bananapus/core-v6/src/structs/JBFee.sol";
|
|
36
|
+
// forge-lint: disable-next-line(unaliased-plain-import)
|
|
37
|
+
import "@bananapus/core-v6/src/structs/JBFundAccessLimitGroup.sol";
|
|
38
|
+
// forge-lint: disable-next-line(unaliased-plain-import)
|
|
39
|
+
import "@bananapus/core-v6/src/structs/JBRuleset.sol";
|
|
40
|
+
// forge-lint: disable-next-line(unaliased-plain-import)
|
|
41
|
+
import "@bananapus/core-v6/src/structs/JBRulesetConfig.sol";
|
|
42
|
+
// forge-lint: disable-next-line(unaliased-plain-import)
|
|
43
|
+
import "@bananapus/core-v6/src/structs/JBRulesetMetadata.sol";
|
|
44
|
+
// forge-lint: disable-next-line(unaliased-plain-import)
|
|
45
|
+
import "@bananapus/core-v6/src/structs/JBPermissionsData.sol";
|
|
46
|
+
// forge-lint: disable-next-line(unaliased-plain-import)
|
|
47
|
+
import "@bananapus/core-v6/src/structs/JBBeforePayRecordedContext.sol";
|
|
48
|
+
// forge-lint: disable-next-line(unaliased-plain-import)
|
|
49
|
+
import "@bananapus/core-v6/src/structs/JBBeforeCashOutRecordedContext.sol";
|
|
50
|
+
// forge-lint: disable-next-line(unaliased-plain-import)
|
|
51
|
+
import "@bananapus/core-v6/src/structs/JBSplit.sol";
|
|
52
|
+
|
|
53
|
+
// forge-lint: disable-next-line(unaliased-plain-import)
|
|
54
|
+
import "@bananapus/core-v6/src/interfaces/IJBTerminal.sol";
|
|
55
|
+
// forge-lint: disable-next-line(unaliased-plain-import)
|
|
56
|
+
import "@bananapus/core-v6/src/interfaces/IJBToken.sol";
|
|
57
|
+
|
|
58
|
+
// forge-lint: disable-next-line(unaliased-plain-import)
|
|
59
|
+
import "@bananapus/permission-ids-v6/src/JBPermissionIds.sol";
|
|
60
|
+
// forge-lint: disable-next-line(unaliased-plain-import)
|
|
61
|
+
import "@bananapus/core-v6/src/libraries/JBRulesetMetadataResolver.sol";
|
|
62
|
+
|
|
63
|
+
// forge-lint: disable-next-line(unused-import)
|
|
64
|
+
import {mulDiv} from "@prb/math/src/Common.sol";
|
|
65
|
+
|
|
66
|
+
// forge-lint: disable-next-line(unaliased-plain-import)
|
|
67
|
+
import "forge-std/Test.sol";
|
|
68
|
+
|
|
69
|
+
// forge-lint: disable-next-line(unaliased-plain-import)
|
|
70
|
+
import "./AccessJBLib.sol";
|
|
71
|
+
|
|
72
|
+
// forge-lint: disable-next-line(unaliased-plain-import)
|
|
73
|
+
import "../../src/structs/JBPayDataHookRulesetConfig.sol";
|
|
74
|
+
// forge-lint: disable-next-line(unaliased-plain-import)
|
|
75
|
+
import "../../src/structs/JBPayDataHookRulesetMetadata.sol";
|
|
76
|
+
|
|
77
|
+
/// @notice Base contract for Juicebox system tests.
|
|
78
|
+
/// @dev Provides common functionality, such as deploying contracts on test setup.
|
|
79
|
+
contract TestBaseWorkflow is Test {
|
|
80
|
+
//*********************************************************************//
|
|
81
|
+
// --------------------- internal stored properties ------------------- //
|
|
82
|
+
//*********************************************************************//
|
|
83
|
+
|
|
84
|
+
address internal projectOwner = address(123);
|
|
85
|
+
address internal beneficiary = address(69_420);
|
|
86
|
+
address internal caller = address(696_969);
|
|
87
|
+
|
|
88
|
+
JBPermissions internal jbPermissions;
|
|
89
|
+
JBProjects internal jbProjects;
|
|
90
|
+
JBPrices internal jbPrices;
|
|
91
|
+
JBDirectory internal jbDirectory;
|
|
92
|
+
JBRulesets internal jbRulesets;
|
|
93
|
+
JBTokens internal jbTokens;
|
|
94
|
+
JBFundAccessLimits internal jbFundAccessLimits;
|
|
95
|
+
JBFeelessAddresses internal jbFeelessAddresses;
|
|
96
|
+
JBSplits internal jbSplits;
|
|
97
|
+
JBController internal jbController;
|
|
98
|
+
JBTerminalStore internal jbTerminalStore;
|
|
99
|
+
JBMultiTerminal internal jbMultiTerminal;
|
|
100
|
+
string internal projectUri;
|
|
101
|
+
IJBToken internal tokenV2;
|
|
102
|
+
|
|
103
|
+
// forge-lint: disable-next-line(mixed-case-variable)
|
|
104
|
+
AccessJBLib internal accessJBLib;
|
|
105
|
+
|
|
106
|
+
//*********************************************************************//
|
|
107
|
+
// --------------------------- test setup ---------------------------- //
|
|
108
|
+
//*********************************************************************//
|
|
109
|
+
|
|
110
|
+
// Deploys and initializes contracts for testing.
|
|
111
|
+
function setUp() public virtual {
|
|
112
|
+
// ---- Set up project ---- //
|
|
113
|
+
jbPermissions = new JBPermissions(address(0));
|
|
114
|
+
vm.label(address(jbPermissions), "JBPermissions");
|
|
115
|
+
|
|
116
|
+
jbProjects = new JBProjects(projectOwner, address(0), address(0));
|
|
117
|
+
vm.label(address(jbProjects), "JBProjects");
|
|
118
|
+
|
|
119
|
+
jbDirectory = new JBDirectory(jbPermissions, jbProjects, projectOwner);
|
|
120
|
+
vm.label(address(jbDirectory), "JBDirectory");
|
|
121
|
+
|
|
122
|
+
jbPrices = new JBPrices(jbDirectory, jbPermissions, jbProjects, projectOwner, address(0));
|
|
123
|
+
vm.label(address(jbPrices), "JBPrices");
|
|
124
|
+
|
|
125
|
+
jbRulesets = new JBRulesets(jbDirectory);
|
|
126
|
+
vm.label(address(jbRulesets), "JBRulesets");
|
|
127
|
+
|
|
128
|
+
jbFundAccessLimits = new JBFundAccessLimits(jbDirectory);
|
|
129
|
+
vm.label(address(jbFundAccessLimits), "JBFundAccessLimits");
|
|
130
|
+
|
|
131
|
+
jbFeelessAddresses = new JBFeelessAddresses(address(69));
|
|
132
|
+
vm.label(address(jbFeelessAddresses), "JBFeelessAddresses");
|
|
133
|
+
|
|
134
|
+
jbTokens = new JBTokens(jbDirectory, new JBERC20(jbPermissions, jbProjects));
|
|
135
|
+
vm.label(address(jbTokens), "JBTokens");
|
|
136
|
+
|
|
137
|
+
jbSplits = new JBSplits(jbDirectory);
|
|
138
|
+
vm.label(address(jbSplits), "JBSplits");
|
|
139
|
+
|
|
140
|
+
jbController = new JBController(
|
|
141
|
+
jbDirectory,
|
|
142
|
+
jbFundAccessLimits,
|
|
143
|
+
jbPermissions,
|
|
144
|
+
jbPrices,
|
|
145
|
+
jbProjects,
|
|
146
|
+
jbRulesets,
|
|
147
|
+
jbSplits,
|
|
148
|
+
jbTokens,
|
|
149
|
+
address(0),
|
|
150
|
+
address(0)
|
|
151
|
+
);
|
|
152
|
+
vm.label(address(jbController), "JBController");
|
|
153
|
+
|
|
154
|
+
vm.prank(projectOwner);
|
|
155
|
+
jbDirectory.setIsAllowedToSetFirstController(address(jbController), true);
|
|
156
|
+
|
|
157
|
+
jbTerminalStore = new JBTerminalStore(jbDirectory, jbPrices, jbRulesets);
|
|
158
|
+
vm.label(address(jbTerminalStore), "JBTerminalStore");
|
|
159
|
+
|
|
160
|
+
accessJBLib = new AccessJBLib();
|
|
161
|
+
|
|
162
|
+
jbMultiTerminal = new JBMultiTerminal(
|
|
163
|
+
jbFeelessAddresses,
|
|
164
|
+
jbPermissions,
|
|
165
|
+
jbProjects,
|
|
166
|
+
jbSplits,
|
|
167
|
+
jbTerminalStore,
|
|
168
|
+
jbTokens,
|
|
169
|
+
IPermit2(address(0)),
|
|
170
|
+
address(0)
|
|
171
|
+
);
|
|
172
|
+
vm.label(address(jbMultiTerminal), "JBMultiTerminal");
|
|
173
|
+
|
|
174
|
+
projectUri = "myIPFSHash";
|
|
175
|
+
|
|
176
|
+
// ---- general setup ---- //
|
|
177
|
+
vm.deal(beneficiary, 100 ether);
|
|
178
|
+
vm.deal(projectOwner, 100 ether);
|
|
179
|
+
vm.deal(caller, 100 ether);
|
|
180
|
+
|
|
181
|
+
vm.label(projectOwner, "projectOwner");
|
|
182
|
+
vm.label(beneficiary, "beneficiary");
|
|
183
|
+
vm.label(caller, "caller");
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
//https://ethereum.stackexchange.com/questions/24248/how-to-calculate-an-ethereum-contracts-address-during-its-creation-using-the-so
|
|
187
|
+
function addressFrom(address origin, uint256 nonce) internal pure returns (address addr) {
|
|
188
|
+
bytes memory data;
|
|
189
|
+
if (nonce == 0x00) {
|
|
190
|
+
data = abi.encodePacked(bytes1(0xd6), bytes1(0x94), origin, bytes1(0x80));
|
|
191
|
+
} else if (nonce <= 0x7f) {
|
|
192
|
+
// forge-lint: disable-next-line(unsafe-typecast)
|
|
193
|
+
data = abi.encodePacked(bytes1(0xd6), bytes1(0x94), origin, uint8(nonce));
|
|
194
|
+
} else if (nonce <= 0xff) {
|
|
195
|
+
// forge-lint: disable-next-line(unsafe-typecast)
|
|
196
|
+
data = abi.encodePacked(bytes1(0xd7), bytes1(0x94), origin, bytes1(0x81), uint8(nonce));
|
|
197
|
+
} else if (nonce <= 0xffff) {
|
|
198
|
+
// forge-lint: disable-next-line(unsafe-typecast)
|
|
199
|
+
data = abi.encodePacked(bytes1(0xd8), bytes1(0x94), origin, bytes1(0x82), uint16(nonce));
|
|
200
|
+
} else if (nonce <= 0xffffff) {
|
|
201
|
+
// forge-lint: disable-next-line(unsafe-typecast)
|
|
202
|
+
data = abi.encodePacked(bytes1(0xd9), bytes1(0x94), origin, bytes1(0x83), uint24(nonce));
|
|
203
|
+
} else {
|
|
204
|
+
// forge-lint: disable-next-line(unsafe-typecast)
|
|
205
|
+
data = abi.encodePacked(bytes1(0xda), bytes1(0x94), origin, bytes1(0x84), uint32(nonce));
|
|
206
|
+
}
|
|
207
|
+
bytes32 hash = keccak256(data);
|
|
208
|
+
assembly ("memory-safe") {
|
|
209
|
+
mstore(0, hash)
|
|
210
|
+
addr := mload(0)
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
}
|