@bananapus/721-hook-v6 0.0.28 → 0.0.30
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 +38 -11
- package/ARCHITECTURE.md +53 -99
- package/AUDIT_INSTRUCTIONS.md +84 -383
- package/CHANGELOG.md +71 -0
- package/README.md +79 -225
- package/RISKS.md +28 -11
- package/SKILLS.md +29 -296
- package/STYLE_GUIDE.md +57 -18
- package/USER_JOURNEYS.md +57 -501
- package/package.json +1 -1
- package/references/operations.md +28 -0
- package/references/runtime.md +32 -0
- package/script/Deploy.s.sol +5 -4
- package/src/JB721TiersHook.sol +1 -1
- package/src/JB721TiersHookDeployer.sol +1 -1
- package/src/JB721TiersHookProjectDeployer.sol +1 -1
- package/src/JB721TiersHookStore.sol +23 -17
- package/src/libraries/JB721Constants.sol +1 -1
- package/src/libraries/JB721TiersRulesetMetadataResolver.sol +1 -1
- package/src/libraries/JBBitmap.sol +1 -1
- package/src/libraries/JBIpfsDecoder.sol +1 -1
- package/src/structs/JB721Tier.sol +5 -11
- package/src/structs/JB721TierConfig.sol +5 -20
- package/src/structs/JB721TierConfigFlags.sol +26 -0
- package/src/structs/JB721TierFlags.sol +17 -0
- package/test/721HookAttacks.t.sol +22 -17
- package/test/E2E/Pay_Mint_Redeem_E2E.t.sol +19 -14
- package/test/Fork.t.sol +69 -54
- package/test/TestAuditGaps.sol +73 -56
- package/test/TestSafeTransferReentrancy.t.sol +4 -4
- package/test/TestVotingUnitsLifecycle.t.sol +11 -11
- package/test/audit/CodexPayCreditsBypassTierSplits.t.sol +10 -7
- package/test/audit/CodexSplitCreditsMismatch.t.sol +10 -7
- package/test/fork/ERC20CashOutFork.t.sol +37 -28
- package/test/fork/ERC20TierSplitFork.t.sol +28 -21
- package/test/fork/IssueTokensForSplitsFork.t.sol +10 -7
- package/test/invariants/handlers/TierLifecycleHandler.sol +10 -7
- package/test/invariants/handlers/TierStoreHandler.sol +10 -7
- package/test/regression/ProjectDeployerRulesets.t.sol +10 -7
- package/test/regression/ReserveBeneficiaryOverwrite.t.sol +6 -6
- package/test/unit/AuditFixes_Unit.t.sol +37 -28
- package/test/unit/adjustTier_Unit.t.sol +268 -202
- package/test/unit/getters_constructor_Unit.t.sol +20 -14
- package/test/unit/mintFor_mintReservesFor_Unit.t.sol +2 -2
- package/test/unit/pay_Unit.t.sol +1 -1
- package/CHANGE_LOG.md +0 -359
package/test/Fork.t.sol
CHANGED
|
@@ -82,6 +82,7 @@ import "../src/structs/JB721TiersRulesetMetadata.sol";
|
|
|
82
82
|
import "../src/libraries/JB721TiersRulesetMetadataResolver.sol";
|
|
83
83
|
// forge-lint: disable-next-line(unaliased-plain-import)
|
|
84
84
|
import "../src/libraries/JB721Constants.sol";
|
|
85
|
+
import {JB721TierConfigFlags} from "../src/structs/JB721TierConfigFlags.sol";
|
|
85
86
|
|
|
86
87
|
/// @title Fork_721Hook_Test
|
|
87
88
|
/// @notice Comprehensive fork tests for JB721TiersHook: lifecycle, features, flags, and adversarial conditions.
|
|
@@ -358,13 +359,15 @@ contract Fork_721Hook_Test is Test {
|
|
|
358
359
|
encodedIPFSUri: IPFS_URI,
|
|
359
360
|
category: uint24(100),
|
|
360
361
|
discountPercent: 0,
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
362
|
+
flags: JB721TierConfigFlags({
|
|
363
|
+
allowOwnerMint: allowOwnerMint,
|
|
364
|
+
useReserveBeneficiaryAsDefault: false,
|
|
365
|
+
transfersPausable: false,
|
|
366
|
+
useVotingUnits: false,
|
|
367
|
+
cantBeRemoved: false,
|
|
368
|
+
cantIncreaseDiscountPercent: false,
|
|
369
|
+
cantBuyWithCredits: false
|
|
370
|
+
}),
|
|
368
371
|
splitPercent: 0,
|
|
369
372
|
splits: new JBSplit[](0)
|
|
370
373
|
});
|
|
@@ -789,13 +792,15 @@ contract Fork_721Hook_Test is Test {
|
|
|
789
792
|
encodedIPFSUri: IPFS_URI,
|
|
790
793
|
category: 200,
|
|
791
794
|
discountPercent: 0,
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
795
|
+
flags: JB721TierConfigFlags({
|
|
796
|
+
allowOwnerMint: false,
|
|
797
|
+
useReserveBeneficiaryAsDefault: false,
|
|
798
|
+
transfersPausable: false,
|
|
799
|
+
useVotingUnits: false,
|
|
800
|
+
cantBeRemoved: false,
|
|
801
|
+
cantIncreaseDiscountPercent: false,
|
|
802
|
+
cantBuyWithCredits: false
|
|
803
|
+
}),
|
|
799
804
|
splitPercent: 0,
|
|
800
805
|
splits: new JBSplit[](0)
|
|
801
806
|
});
|
|
@@ -822,13 +827,15 @@ contract Fork_721Hook_Test is Test {
|
|
|
822
827
|
encodedIPFSUri: IPFS_URI,
|
|
823
828
|
category: 200,
|
|
824
829
|
discountPercent: 0,
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
830
|
+
flags: JB721TierConfigFlags({
|
|
831
|
+
allowOwnerMint: true,
|
|
832
|
+
useReserveBeneficiaryAsDefault: false,
|
|
833
|
+
transfersPausable: false,
|
|
834
|
+
useVotingUnits: false,
|
|
835
|
+
cantBeRemoved: false,
|
|
836
|
+
cantIncreaseDiscountPercent: false,
|
|
837
|
+
cantBuyWithCredits: false
|
|
838
|
+
}),
|
|
832
839
|
splitPercent: 0,
|
|
833
840
|
splits: new JBSplit[](0)
|
|
834
841
|
});
|
|
@@ -841,7 +848,7 @@ contract Fork_721Hook_Test is Test {
|
|
|
841
848
|
/// @notice cantBeRemoved: removing an immutable tier should revert.
|
|
842
849
|
function test_fork_cantBeRemoved_reverts() public {
|
|
843
850
|
JB721TierConfig[] memory tierConfigs = _makeStandardTiers(1, 10, false);
|
|
844
|
-
tierConfigs[0].cantBeRemoved = true;
|
|
851
|
+
tierConfigs[0].flags.cantBeRemoved = true;
|
|
845
852
|
JB721TiersHookFlags memory flags = _defaultFlags();
|
|
846
853
|
(, address hook) = _launchProject(tierConfigs, flags, 5000, true, 0x00);
|
|
847
854
|
|
|
@@ -906,7 +913,7 @@ contract Fork_721Hook_Test is Test {
|
|
|
906
913
|
function test_fork_cannotIncreaseDiscount() public {
|
|
907
914
|
JB721TierConfig[] memory tierConfigs = _makeStandardTiers(1, 10, false);
|
|
908
915
|
tierConfigs[0].discountPercent = 50;
|
|
909
|
-
tierConfigs[0].cantIncreaseDiscountPercent = true;
|
|
916
|
+
tierConfigs[0].flags.cantIncreaseDiscountPercent = true;
|
|
910
917
|
JB721TiersHookFlags memory flags = _defaultFlags();
|
|
911
918
|
(, address hook) = _launchProject(tierConfigs, flags, 5000, true, 0x00);
|
|
912
919
|
|
|
@@ -997,7 +1004,7 @@ contract Fork_721Hook_Test is Test {
|
|
|
997
1004
|
/// @notice transfersPausable tier flag + ruleset metadata pauses transfers.
|
|
998
1005
|
function test_fork_transfersPaused_reverts() public {
|
|
999
1006
|
JB721TierConfig[] memory tierConfigs = _makeStandardTiers(1, 10, false);
|
|
1000
|
-
tierConfigs[0].transfersPausable = true;
|
|
1007
|
+
tierConfigs[0].flags.transfersPausable = true;
|
|
1001
1008
|
JB721TiersHookFlags memory flags = _defaultFlags();
|
|
1002
1009
|
|
|
1003
1010
|
// Pack 721 metadata: bit 0 = pauseTransfers = true.
|
|
@@ -1022,7 +1029,7 @@ contract Fork_721Hook_Test is Test {
|
|
|
1022
1029
|
/// @notice Transfer works when transfersPausable=true but ruleset metadata doesn't pause.
|
|
1023
1030
|
function test_fork_transfersPausable_notPaused_works() public {
|
|
1024
1031
|
JB721TierConfig[] memory tierConfigs = _makeStandardTiers(1, 10, false);
|
|
1025
|
-
tierConfigs[0].transfersPausable = true;
|
|
1032
|
+
tierConfigs[0].flags.transfersPausable = true;
|
|
1026
1033
|
JB721TiersHookFlags memory flags = _defaultFlags();
|
|
1027
1034
|
|
|
1028
1035
|
// 721 metadata: transfers NOT paused.
|
|
@@ -1130,13 +1137,15 @@ contract Fork_721Hook_Test is Test {
|
|
|
1130
1137
|
encodedIPFSUri: IPFS_URI,
|
|
1131
1138
|
category: 200,
|
|
1132
1139
|
discountPercent: 0,
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
+
flags: JB721TierConfigFlags({
|
|
1141
|
+
allowOwnerMint: false,
|
|
1142
|
+
useReserveBeneficiaryAsDefault: false,
|
|
1143
|
+
transfersPausable: false,
|
|
1144
|
+
useVotingUnits: false,
|
|
1145
|
+
cantBeRemoved: false,
|
|
1146
|
+
cantIncreaseDiscountPercent: false,
|
|
1147
|
+
cantBuyWithCredits: false
|
|
1148
|
+
}),
|
|
1140
1149
|
splitPercent: 0,
|
|
1141
1150
|
splits: new JBSplit[](0)
|
|
1142
1151
|
});
|
|
@@ -1298,7 +1307,7 @@ contract Fork_721Hook_Test is Test {
|
|
|
1298
1307
|
/// @notice Custom voting units (useVotingUnits=true) uses specified value.
|
|
1299
1308
|
function test_fork_customVotingUnits() public {
|
|
1300
1309
|
JB721TierConfig[] memory tierConfigs = _makeStandardTiers(1, 10, false);
|
|
1301
|
-
tierConfigs[0].useVotingUnits = true;
|
|
1310
|
+
tierConfigs[0].flags.useVotingUnits = true;
|
|
1302
1311
|
tierConfigs[0].votingUnits = 42;
|
|
1303
1312
|
JB721TiersHookFlags memory flags = _defaultFlags();
|
|
1304
1313
|
(uint256 projectId, address hook) = _launchProject(tierConfigs, flags, 5000, true, 0x00);
|
|
@@ -1524,13 +1533,15 @@ contract Fork_721Hook_Test is Test {
|
|
|
1524
1533
|
encodedIPFSUri: IPFS_URI,
|
|
1525
1534
|
category: 200,
|
|
1526
1535
|
discountPercent: 0,
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1536
|
+
flags: JB721TierConfigFlags({
|
|
1537
|
+
allowOwnerMint: false,
|
|
1538
|
+
useReserveBeneficiaryAsDefault: false,
|
|
1539
|
+
transfersPausable: false,
|
|
1540
|
+
useVotingUnits: false,
|
|
1541
|
+
cantBeRemoved: false,
|
|
1542
|
+
cantIncreaseDiscountPercent: false,
|
|
1543
|
+
cantBuyWithCredits: false
|
|
1544
|
+
}),
|
|
1534
1545
|
splitPercent: 0,
|
|
1535
1546
|
splits: new JBSplit[](0)
|
|
1536
1547
|
});
|
|
@@ -1771,13 +1782,15 @@ contract Fork_721Hook_Test is Test {
|
|
|
1771
1782
|
encodedIPFSUri: IPFS_URI,
|
|
1772
1783
|
category: uint24((i + 1) * 100), // Categories: 100, 200, 300
|
|
1773
1784
|
discountPercent: 0,
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1785
|
+
flags: JB721TierConfigFlags({
|
|
1786
|
+
allowOwnerMint: false,
|
|
1787
|
+
useReserveBeneficiaryAsDefault: false,
|
|
1788
|
+
transfersPausable: false,
|
|
1789
|
+
useVotingUnits: false,
|
|
1790
|
+
cantBeRemoved: false,
|
|
1791
|
+
cantIncreaseDiscountPercent: false,
|
|
1792
|
+
cantBuyWithCredits: false
|
|
1793
|
+
}),
|
|
1781
1794
|
splitPercent: 0,
|
|
1782
1795
|
splits: new JBSplit[](0)
|
|
1783
1796
|
});
|
|
@@ -2047,13 +2060,15 @@ contract Fork_721Hook_Test is Test {
|
|
|
2047
2060
|
encodedIPFSUri: IPFS_URI,
|
|
2048
2061
|
category: category,
|
|
2049
2062
|
discountPercent: 0,
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
2063
|
+
flags: JB721TierConfigFlags({
|
|
2064
|
+
allowOwnerMint: false,
|
|
2065
|
+
useReserveBeneficiaryAsDefault: false,
|
|
2066
|
+
transfersPausable: false,
|
|
2067
|
+
useVotingUnits: false,
|
|
2068
|
+
cantBeRemoved: false,
|
|
2069
|
+
cantIncreaseDiscountPercent: false,
|
|
2070
|
+
cantBuyWithCredits: false
|
|
2071
|
+
}),
|
|
2057
2072
|
splitPercent: splitPct,
|
|
2058
2073
|
splits: splits
|
|
2059
2074
|
});
|
package/test/TestAuditGaps.sol
CHANGED
|
@@ -10,6 +10,7 @@ import {IJBSplitHook} from "@bananapus/core-v6/src/interfaces/IJBSplitHook.sol";
|
|
|
10
10
|
import {IJBSplits} from "@bananapus/core-v6/src/interfaces/IJBSplits.sol";
|
|
11
11
|
import {IJBDirectory} from "@bananapus/core-v6/src/interfaces/IJBDirectory.sol";
|
|
12
12
|
import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol";
|
|
13
|
+
import {JB721TierConfigFlags} from "../src/structs/JB721TierConfigFlags.sol";
|
|
13
14
|
|
|
14
15
|
// =====================================================================
|
|
15
16
|
// Malicious split hook that attempts reentrancy during fund distribution
|
|
@@ -450,13 +451,15 @@ contract TestAuditGaps_GasLimits is UnitTestSetup {
|
|
|
450
451
|
// forge-lint: disable-next-line(unsafe-typecast)
|
|
451
452
|
category: uint24(i + 1), // Ascending categories
|
|
452
453
|
discountPercent: 0,
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
454
|
+
flags: JB721TierConfigFlags({
|
|
455
|
+
allowOwnerMint: false,
|
|
456
|
+
useReserveBeneficiaryAsDefault: false,
|
|
457
|
+
transfersPausable: false,
|
|
458
|
+
useVotingUnits: false,
|
|
459
|
+
cantBeRemoved: false,
|
|
460
|
+
cantIncreaseDiscountPercent: false,
|
|
461
|
+
cantBuyWithCredits: false
|
|
462
|
+
}),
|
|
460
463
|
splitPercent: 0,
|
|
461
464
|
splits: new JBSplit[](0)
|
|
462
465
|
});
|
|
@@ -504,13 +507,15 @@ contract TestAuditGaps_GasLimits is UnitTestSetup {
|
|
|
504
507
|
// forge-lint: disable-next-line(unsafe-typecast)
|
|
505
508
|
category: uint24(i + 1),
|
|
506
509
|
discountPercent: 0,
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
510
|
+
flags: JB721TierConfigFlags({
|
|
511
|
+
allowOwnerMint: false,
|
|
512
|
+
useReserveBeneficiaryAsDefault: false,
|
|
513
|
+
transfersPausable: false,
|
|
514
|
+
useVotingUnits: false,
|
|
515
|
+
cantBeRemoved: false,
|
|
516
|
+
cantIncreaseDiscountPercent: false,
|
|
517
|
+
cantBuyWithCredits: false
|
|
518
|
+
}),
|
|
514
519
|
splitPercent: 0,
|
|
515
520
|
splits: new JBSplit[](0)
|
|
516
521
|
});
|
|
@@ -560,13 +565,15 @@ contract TestAuditGaps_GasLimits is UnitTestSetup {
|
|
|
560
565
|
// forge-lint: disable-next-line(unsafe-typecast)
|
|
561
566
|
category: uint24(i + 1),
|
|
562
567
|
discountPercent: 0,
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
568
|
+
flags: JB721TierConfigFlags({
|
|
569
|
+
allowOwnerMint: false,
|
|
570
|
+
useReserveBeneficiaryAsDefault: false,
|
|
571
|
+
transfersPausable: false,
|
|
572
|
+
useVotingUnits: false,
|
|
573
|
+
cantBeRemoved: false,
|
|
574
|
+
cantIncreaseDiscountPercent: false,
|
|
575
|
+
cantBuyWithCredits: false
|
|
576
|
+
}),
|
|
570
577
|
splitPercent: 0,
|
|
571
578
|
splits: new JBSplit[](0)
|
|
572
579
|
});
|
|
@@ -662,13 +669,15 @@ contract TestAuditGaps_GasLimits is UnitTestSetup {
|
|
|
662
669
|
// forge-lint: disable-next-line(unsafe-typecast)
|
|
663
670
|
category: uint24(i + 1),
|
|
664
671
|
discountPercent: 0,
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
+
flags: JB721TierConfigFlags({
|
|
673
|
+
allowOwnerMint: false,
|
|
674
|
+
useReserveBeneficiaryAsDefault: false,
|
|
675
|
+
transfersPausable: false,
|
|
676
|
+
useVotingUnits: false,
|
|
677
|
+
cantBeRemoved: false,
|
|
678
|
+
cantIncreaseDiscountPercent: false,
|
|
679
|
+
cantBuyWithCredits: false
|
|
680
|
+
}),
|
|
672
681
|
splitPercent: 0,
|
|
673
682
|
splits: new JBSplit[](0)
|
|
674
683
|
});
|
|
@@ -712,13 +721,15 @@ contract TestAuditGaps_GasLimits is UnitTestSetup {
|
|
|
712
721
|
// forge-lint: disable-next-line(unsafe-typecast)
|
|
713
722
|
category: uint24(i + 1),
|
|
714
723
|
discountPercent: 0,
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
724
|
+
flags: JB721TierConfigFlags({
|
|
725
|
+
allowOwnerMint: false,
|
|
726
|
+
useReserveBeneficiaryAsDefault: false,
|
|
727
|
+
transfersPausable: false,
|
|
728
|
+
useVotingUnits: false,
|
|
729
|
+
cantBeRemoved: false,
|
|
730
|
+
cantIncreaseDiscountPercent: false,
|
|
731
|
+
cantBuyWithCredits: false
|
|
732
|
+
}),
|
|
722
733
|
splitPercent: 0,
|
|
723
734
|
splits: new JBSplit[](0)
|
|
724
735
|
});
|
|
@@ -774,13 +785,15 @@ contract TestAuditGaps_GasLimits is UnitTestSetup {
|
|
|
774
785
|
// forge-lint: disable-next-line(unsafe-typecast)
|
|
775
786
|
category: uint24(i + 1),
|
|
776
787
|
discountPercent: 0,
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
788
|
+
flags: JB721TierConfigFlags({
|
|
789
|
+
allowOwnerMint: false,
|
|
790
|
+
useReserveBeneficiaryAsDefault: false,
|
|
791
|
+
transfersPausable: false,
|
|
792
|
+
useVotingUnits: false,
|
|
793
|
+
cantBeRemoved: false,
|
|
794
|
+
cantIncreaseDiscountPercent: false,
|
|
795
|
+
cantBuyWithCredits: false
|
|
796
|
+
}),
|
|
784
797
|
splitPercent: 0,
|
|
785
798
|
splits: new JBSplit[](0)
|
|
786
799
|
});
|
|
@@ -847,13 +860,15 @@ contract TestAuditGaps_GasLimits is UnitTestSetup {
|
|
|
847
860
|
// forge-lint: disable-next-line(unsafe-typecast)
|
|
848
861
|
category: uint24(i + 1),
|
|
849
862
|
discountPercent: 0,
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
863
|
+
flags: JB721TierConfigFlags({
|
|
864
|
+
allowOwnerMint: false,
|
|
865
|
+
useReserveBeneficiaryAsDefault: false,
|
|
866
|
+
transfersPausable: false,
|
|
867
|
+
useVotingUnits: false,
|
|
868
|
+
cantBeRemoved: false,
|
|
869
|
+
cantIncreaseDiscountPercent: false,
|
|
870
|
+
cantBuyWithCredits: false
|
|
871
|
+
}),
|
|
857
872
|
splitPercent: 0,
|
|
858
873
|
splits: new JBSplit[](0)
|
|
859
874
|
});
|
|
@@ -1043,13 +1058,15 @@ contract TestAuditGaps_GasLimits is UnitTestSetup {
|
|
|
1043
1058
|
// forge-lint: disable-next-line(unsafe-typecast)
|
|
1044
1059
|
category: uint24(i + 1),
|
|
1045
1060
|
discountPercent: 0,
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1061
|
+
flags: JB721TierConfigFlags({
|
|
1062
|
+
allowOwnerMint: false,
|
|
1063
|
+
useReserveBeneficiaryAsDefault: false,
|
|
1064
|
+
transfersPausable: false,
|
|
1065
|
+
useVotingUnits: false,
|
|
1066
|
+
cantBeRemoved: false,
|
|
1067
|
+
cantIncreaseDiscountPercent: false,
|
|
1068
|
+
cantBuyWithCredits: false
|
|
1069
|
+
}),
|
|
1053
1070
|
splitPercent: 0,
|
|
1054
1071
|
splits: new JBSplit[](0)
|
|
1055
1072
|
});
|
|
@@ -84,7 +84,7 @@ contract TestSafeTransferReentrancy is UnitTestSetup {
|
|
|
84
84
|
/// The re-entry fails because the receiver is not registered as a terminal.
|
|
85
85
|
function test_safeTransferFrom_maliciousReceiver_cannotReenterAfterPay() public {
|
|
86
86
|
// Set up hook with tiers and mint an NFT.
|
|
87
|
-
defaultTierConfig.allowOwnerMint = true;
|
|
87
|
+
defaultTierConfig.flags.allowOwnerMint = true;
|
|
88
88
|
defaultTierConfig.reserveFrequency = 0;
|
|
89
89
|
ForTest_JB721TiersHook testHook = _initializeForTestHook(10);
|
|
90
90
|
|
|
@@ -161,7 +161,7 @@ contract TestSafeTransferReentrancy is UnitTestSetup {
|
|
|
161
161
|
/// The call is blocked by permission checks.
|
|
162
162
|
function test_safeTransferFrom_maliciousReceiver_cannotReenterAdjustTiers() public {
|
|
163
163
|
// Set up hook with tiers and mint an NFT.
|
|
164
|
-
defaultTierConfig.allowOwnerMint = true;
|
|
164
|
+
defaultTierConfig.flags.allowOwnerMint = true;
|
|
165
165
|
defaultTierConfig.reserveFrequency = 0;
|
|
166
166
|
ForTest_JB721TiersHook testHook = _initializeForTestHook(10);
|
|
167
167
|
|
|
@@ -205,7 +205,7 @@ contract TestSafeTransferReentrancy is UnitTestSetup {
|
|
|
205
205
|
/// and a re-transfer should succeed with correct state.
|
|
206
206
|
function test_safeTransferFrom_maliciousReceiver_retransferDuringCallback() public {
|
|
207
207
|
// Set up hook with tiers and mint an NFT.
|
|
208
|
-
defaultTierConfig.allowOwnerMint = true;
|
|
208
|
+
defaultTierConfig.flags.allowOwnerMint = true;
|
|
209
209
|
defaultTierConfig.reserveFrequency = 0;
|
|
210
210
|
ForTest_JB721TiersHook testHook = _initializeForTestHook(10);
|
|
211
211
|
|
|
@@ -258,7 +258,7 @@ contract TestSafeTransferReentrancy is UnitTestSetup {
|
|
|
258
258
|
/// tier balances, voting units, and firstOwner tracking consistent.
|
|
259
259
|
function test_safeTransferFrom_normalReceiver_stateConsistent() public {
|
|
260
260
|
// Set up hook with tiers and mint an NFT.
|
|
261
|
-
defaultTierConfig.allowOwnerMint = true;
|
|
261
|
+
defaultTierConfig.flags.allowOwnerMint = true;
|
|
262
262
|
defaultTierConfig.reserveFrequency = 0;
|
|
263
263
|
ForTest_JB721TiersHook testHook = _initializeForTestHook(10);
|
|
264
264
|
|
|
@@ -20,9 +20,9 @@ contract TestVotingUnitsLifecycle is UnitTestSetup {
|
|
|
20
20
|
/// through the full lifecycle: mint to user A, transfer to user B, burn by user B.
|
|
21
21
|
function test_votingUnits_mintTransferBurn_lifecycle() public {
|
|
22
22
|
// Configure a tier with custom voting units.
|
|
23
|
-
defaultTierConfig.allowOwnerMint = true;
|
|
23
|
+
defaultTierConfig.flags.allowOwnerMint = true;
|
|
24
24
|
defaultTierConfig.reserveFrequency = 0;
|
|
25
|
-
defaultTierConfig.useVotingUnits = true;
|
|
25
|
+
defaultTierConfig.flags.useVotingUnits = true;
|
|
26
26
|
defaultTierConfig.votingUnits = 100;
|
|
27
27
|
|
|
28
28
|
ForTest_JB721TiersHook testHook = _initializeForTestHook(1);
|
|
@@ -75,9 +75,9 @@ contract TestVotingUnitsLifecycle is UnitTestSetup {
|
|
|
75
75
|
/// and update properly when NFTs are transferred between users.
|
|
76
76
|
function test_votingUnits_multiTier_aggregation() public {
|
|
77
77
|
// Configure tiers with different custom voting units.
|
|
78
|
-
defaultTierConfig.allowOwnerMint = true;
|
|
78
|
+
defaultTierConfig.flags.allowOwnerMint = true;
|
|
79
79
|
defaultTierConfig.reserveFrequency = 0;
|
|
80
|
-
defaultTierConfig.useVotingUnits = true;
|
|
80
|
+
defaultTierConfig.flags.useVotingUnits = true;
|
|
81
81
|
|
|
82
82
|
ForTest_JB721TiersHook testHook = _initializeForTestHook(3);
|
|
83
83
|
IJB721TiersHookStore hookStore = testHook.STORE();
|
|
@@ -149,9 +149,9 @@ contract TestVotingUnitsLifecycle is UnitTestSetup {
|
|
|
149
149
|
/// @notice Verifies that when useVotingUnits is false, the tier price is used as voting power.
|
|
150
150
|
function test_votingUnits_priceBasedVoting_lifecycle() public {
|
|
151
151
|
// Configure tiers WITHOUT custom voting units (price-based voting).
|
|
152
|
-
defaultTierConfig.allowOwnerMint = true;
|
|
152
|
+
defaultTierConfig.flags.allowOwnerMint = true;
|
|
153
153
|
defaultTierConfig.reserveFrequency = 0;
|
|
154
|
-
defaultTierConfig.useVotingUnits = false;
|
|
154
|
+
defaultTierConfig.flags.useVotingUnits = false;
|
|
155
155
|
defaultTierConfig.votingUnits = 0;
|
|
156
156
|
|
|
157
157
|
ForTest_JB721TiersHook testHook = _initializeForTestHook(3);
|
|
@@ -200,9 +200,9 @@ contract TestVotingUnitsLifecycle is UnitTestSetup {
|
|
|
200
200
|
/// @notice Verifies that voting units scale correctly when a user owns multiple NFTs from one tier.
|
|
201
201
|
function test_votingUnits_multipleMintsSameTier() public {
|
|
202
202
|
// Configure tier with custom voting units.
|
|
203
|
-
defaultTierConfig.allowOwnerMint = true;
|
|
203
|
+
defaultTierConfig.flags.allowOwnerMint = true;
|
|
204
204
|
defaultTierConfig.reserveFrequency = 0;
|
|
205
|
-
defaultTierConfig.useVotingUnits = true;
|
|
205
|
+
defaultTierConfig.flags.useVotingUnits = true;
|
|
206
206
|
defaultTierConfig.votingUnits = 50;
|
|
207
207
|
|
|
208
208
|
ForTest_JB721TiersHook testHook = _initializeForTestHook(1);
|
|
@@ -242,7 +242,7 @@ contract TestVotingUnitsLifecycle is UnitTestSetup {
|
|
|
242
242
|
// ---------------------------------------------------------------
|
|
243
243
|
/// @notice Verifies that addresses with no NFTs always return 0 voting units.
|
|
244
244
|
function test_votingUnits_zeroForNonHolders() public {
|
|
245
|
-
defaultTierConfig.useVotingUnits = true;
|
|
245
|
+
defaultTierConfig.flags.useVotingUnits = true;
|
|
246
246
|
defaultTierConfig.votingUnits = 100;
|
|
247
247
|
|
|
248
248
|
ForTest_JB721TiersHook testHook = _initializeForTestHook(5);
|
|
@@ -260,9 +260,9 @@ contract TestVotingUnitsLifecycle is UnitTestSetup {
|
|
|
260
260
|
/// @notice Verifies that voting units work correctly when some tiers use custom voting units
|
|
261
261
|
/// and others use price-based voting. The tier with useVotingUnits=false should use price.
|
|
262
262
|
function test_votingUnits_mixedTierConfigs() public {
|
|
263
|
-
defaultTierConfig.allowOwnerMint = true;
|
|
263
|
+
defaultTierConfig.flags.allowOwnerMint = true;
|
|
264
264
|
defaultTierConfig.reserveFrequency = 0;
|
|
265
|
-
defaultTierConfig.useVotingUnits = true;
|
|
265
|
+
defaultTierConfig.flags.useVotingUnits = true;
|
|
266
266
|
defaultTierConfig.votingUnits = 100;
|
|
267
267
|
|
|
268
268
|
ForTest_JB721TiersHook testHook = _initializeForTestHook(3);
|
|
@@ -11,6 +11,7 @@ import {JBAfterPayRecordedContext} from "@bananapus/core-v6/src/structs/JBAfterP
|
|
|
11
11
|
import {JBPayHookSpecification} from "@bananapus/core-v6/src/structs/JBPayHookSpecification.sol";
|
|
12
12
|
import {JBSplit} from "@bananapus/core-v6/src/structs/JBSplit.sol";
|
|
13
13
|
import {IJBSplitHook} from "@bananapus/core-v6/src/interfaces/IJBSplitHook.sol";
|
|
14
|
+
import {JB721TierConfigFlags} from "../../src/structs/JB721TierConfigFlags.sol";
|
|
14
15
|
|
|
15
16
|
contract CodexPayCreditsBypassTierSplits is UnitTestSetup {
|
|
16
17
|
address internal splitBeneficiary = makeAddr("splitBeneficiary");
|
|
@@ -118,13 +119,15 @@ contract CodexPayCreditsBypassTierSplits is UnitTestSetup {
|
|
|
118
119
|
encodedIPFSUri: bytes32(uint256(0x1234)),
|
|
119
120
|
category: 1,
|
|
120
121
|
discountPercent: 0,
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
122
|
+
flags: JB721TierConfigFlags({
|
|
123
|
+
allowOwnerMint: false,
|
|
124
|
+
useReserveBeneficiaryAsDefault: false,
|
|
125
|
+
transfersPausable: false,
|
|
126
|
+
useVotingUnits: false,
|
|
127
|
+
cantBeRemoved: false,
|
|
128
|
+
cantIncreaseDiscountPercent: false,
|
|
129
|
+
cantBuyWithCredits: false
|
|
130
|
+
}),
|
|
128
131
|
splitPercent: 1_000_000_000,
|
|
129
132
|
splits: new JBSplit[](0)
|
|
130
133
|
});
|
|
@@ -10,6 +10,7 @@ import {JBBeforePayRecordedContext} from "@bananapus/core-v6/src/structs/JBBefor
|
|
|
10
10
|
import {JBPayHookSpecification} from "@bananapus/core-v6/src/structs/JBPayHookSpecification.sol";
|
|
11
11
|
import {JBSplit} from "@bananapus/core-v6/src/structs/JBSplit.sol";
|
|
12
12
|
import {IJBSplitHook} from "@bananapus/core-v6/src/interfaces/IJBSplitHook.sol";
|
|
13
|
+
import {JB721TierConfigFlags} from "../../src/structs/JB721TierConfigFlags.sol";
|
|
13
14
|
|
|
14
15
|
/// @notice Regression test: split metadata is proportionally scaled when credits fund a split-bearing tier mint.
|
|
15
16
|
/// @dev Previously (pre-fix), the per-tier split amounts were left at the uncapped value, trapping forwarded ETH.
|
|
@@ -121,13 +122,15 @@ contract CodexSplitCreditsMismatch is UnitTestSetup {
|
|
|
121
122
|
encodedIPFSUri: bytes32(uint256(0x1234)),
|
|
122
123
|
category: 1,
|
|
123
124
|
discountPercent: 0,
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
125
|
+
flags: JB721TierConfigFlags({
|
|
126
|
+
allowOwnerMint: false,
|
|
127
|
+
useReserveBeneficiaryAsDefault: false,
|
|
128
|
+
transfersPausable: false,
|
|
129
|
+
useVotingUnits: false,
|
|
130
|
+
cantBeRemoved: false,
|
|
131
|
+
cantIncreaseDiscountPercent: false,
|
|
132
|
+
cantBuyWithCredits: false
|
|
133
|
+
}),
|
|
131
134
|
splitPercent: 1_000_000_000,
|
|
132
135
|
splits: new JBSplit[](0)
|
|
133
136
|
});
|