@rev-net/core-v6 0.0.11 → 0.0.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (81) hide show
  1. package/ADMINISTRATION.md +7 -7
  2. package/ARCHITECTURE.md +11 -11
  3. package/AUDIT_INSTRUCTIONS.md +295 -0
  4. package/CHANGE_LOG.md +316 -0
  5. package/README.md +9 -6
  6. package/RISKS.md +180 -35
  7. package/SKILLS.md +9 -11
  8. package/STYLE_GUIDE.md +14 -1
  9. package/USER_JOURNEYS.md +489 -0
  10. package/package.json +9 -9
  11. package/script/Deploy.s.sol +124 -40
  12. package/script/helpers/RevnetCoreDeploymentLib.sol +19 -6
  13. package/src/REVDeployer.sol +183 -175
  14. package/src/REVLoans.sol +65 -28
  15. package/src/interfaces/IREVDeployer.sol +25 -23
  16. package/src/structs/REV721TiersHookFlags.sol +1 -0
  17. package/src/structs/REVAutoIssuance.sol +1 -0
  18. package/src/structs/REVBaseline721HookConfig.sol +1 -0
  19. package/src/structs/REVConfig.sol +1 -0
  20. package/src/structs/REVCroptopAllowedPost.sol +1 -0
  21. package/src/structs/REVDeploy721TiersHookConfig.sol +13 -14
  22. package/src/structs/REVDescription.sol +1 -0
  23. package/src/structs/REVLoan.sol +1 -0
  24. package/src/structs/REVLoanSource.sol +1 -0
  25. package/src/structs/REVStageConfig.sol +1 -0
  26. package/src/structs/REVSuckerDeploymentConfig.sol +1 -0
  27. package/test/REV.integrations.t.sol +148 -19
  28. package/test/REVAutoIssuanceFuzz.t.sol +31 -6
  29. package/test/REVDeployerRegressions.t.sol +47 -9
  30. package/test/REVInvincibility.t.sol +83 -19
  31. package/test/REVInvincibilityHandler.sol +29 -0
  32. package/test/REVLifecycle.t.sol +36 -6
  33. package/test/REVLoans.invariants.t.sol +64 -10
  34. package/test/REVLoansAttacks.t.sol +54 -9
  35. package/test/REVLoansFeeRecovery.t.sol +61 -15
  36. package/test/REVLoansFindings.t.sol +42 -9
  37. package/test/REVLoansRegressions.t.sol +33 -6
  38. package/test/REVLoansSourceFeeRecovery.t.sol +491 -0
  39. package/test/REVLoansSourced.t.sol +79 -17
  40. package/test/REVLoansUnSourced.t.sol +61 -10
  41. package/test/TestBurnHeldTokens.t.sol +47 -11
  42. package/test/TestCEIPattern.t.sol +37 -6
  43. package/test/TestCashOutCallerValidation.t.sol +41 -8
  44. package/test/TestConversionDocumentation.t.sol +50 -13
  45. package/test/TestCrossCurrencyReclaim.t.sol +584 -0
  46. package/test/TestCrossSourceReallocation.t.sol +37 -6
  47. package/test/TestERC2771MetaTx.t.sol +557 -0
  48. package/test/TestEmptyBuybackSpecs.t.sol +45 -10
  49. package/test/TestFlashLoanSurplus.t.sol +39 -7
  50. package/test/TestHookArrayOOB.t.sol +42 -13
  51. package/test/TestLiquidationBehavior.t.sol +37 -7
  52. package/test/TestLoanSourceRotation.t.sol +525 -0
  53. package/test/TestLongTailEconomics.t.sol +651 -0
  54. package/test/TestLowFindings.t.sol +80 -8
  55. package/test/TestMixedFixes.t.sol +43 -9
  56. package/test/TestPermit2Signatures.t.sol +657 -0
  57. package/test/TestReallocationSandwich.t.sol +384 -0
  58. package/test/TestRevnetRegressions.t.sol +324 -0
  59. package/test/TestSplitWeightAdjustment.t.sol +52 -13
  60. package/test/TestSplitWeightE2E.t.sol +53 -18
  61. package/test/TestSplitWeightFork.t.sol +66 -21
  62. package/test/TestStageTransitionBorrowable.t.sol +38 -6
  63. package/test/TestSwapTerminalPermission.t.sol +37 -7
  64. package/test/TestUint112Overflow.t.sol +39 -6
  65. package/test/TestZeroRepayment.t.sol +37 -6
  66. package/test/fork/ForkTestBase.sol +66 -17
  67. package/test/fork/TestCashOutFork.t.sol +9 -3
  68. package/test/fork/TestLoanBorrowFork.t.sol +1 -0
  69. package/test/fork/TestLoanCrossRulesetFork.t.sol +11 -3
  70. package/test/fork/TestLoanLiquidationFork.t.sol +1 -0
  71. package/test/fork/TestLoanReallocateFork.t.sol +1 -0
  72. package/test/fork/TestLoanRepayFork.t.sol +1 -0
  73. package/test/fork/TestLoanTransferFork.t.sol +133 -0
  74. package/test/fork/TestSplitWeightFork.t.sol +3 -0
  75. package/test/helpers/REVEmpty721Config.sol +46 -0
  76. package/test/mock/MockBuybackDataHook.sol +1 -0
  77. package/test/regression/TestBurnPermissionRequired.t.sol +267 -0
  78. package/test/regression/TestCrossRevnetLiquidation.t.sol +228 -0
  79. package/test/regression/TestCumulativeLoanCounter.t.sol +38 -8
  80. package/test/regression/TestLiquidateGapHandling.t.sol +40 -8
  81. package/test/regression/TestZeroPriceFeed.t.sol +396 -0
@@ -1,22 +1,29 @@
1
1
  // SPDX-License-Identifier: MIT
2
2
  pragma solidity 0.8.26;
3
3
 
4
+ // forge-lint: disable-next-line(unaliased-plain-import)
4
5
  import "forge-std/Test.sol";
6
+ // forge-lint: disable-next-line(unaliased-plain-import)
5
7
  import /* {*} from */ "@bananapus/core-v6/test/helpers/TestBaseWorkflow.sol";
8
+ // forge-lint: disable-next-line(unaliased-plain-import)
6
9
  import /* {*} from */ "./../src/REVDeployer.sol";
10
+ // forge-lint: disable-next-line(unaliased-plain-import)
7
11
  import "@croptop/core-v6/src/CTPublisher.sol";
8
12
  import {MockBuybackDataHookMintPath} from "./mock/MockBuybackDataHookMintPath.sol";
9
- import {MockBuybackDataHook} from "./mock/MockBuybackDataHook.sol";
13
+ // forge-lint: disable-next-line(unaliased-plain-import)
10
14
  import "@bananapus/core-v6/script/helpers/CoreDeploymentLib.sol";
15
+ // forge-lint: disable-next-line(unaliased-plain-import)
11
16
  import "@bananapus/721-hook-v6/script/helpers/Hook721DeploymentLib.sol";
17
+ // forge-lint: disable-next-line(unaliased-plain-import)
12
18
  import "@bananapus/suckers-v6/script/helpers/SuckerDeploymentLib.sol";
19
+ // forge-lint: disable-next-line(unaliased-plain-import)
13
20
  import "@croptop/core-v6/script/helpers/CroptopDeploymentLib.sol";
21
+ // forge-lint: disable-next-line(unaliased-plain-import)
14
22
  import "@bananapus/router-terminal-v6/script/helpers/RouterTerminalDeploymentLib.sol";
15
23
  import {JBConstants} from "@bananapus/core-v6/src/libraries/JBConstants.sol";
16
24
  import {JBAccountingContext} from "@bananapus/core-v6/src/structs/JBAccountingContext.sol";
17
25
  import {REVLoans} from "../src/REVLoans.sol";
18
26
  import {REVStageConfig, REVAutoIssuance} from "../src/structs/REVStageConfig.sol";
19
- import {REVLoanSource} from "../src/structs/REVLoanSource.sol";
20
27
  import {REVDescription} from "../src/structs/REVDescription.sol";
21
28
  import {IREVLoans} from "./../src/interfaces/IREVLoans.sol";
22
29
  import {JBSuckerDeployerConfig} from "@bananapus/suckers-v6/src/structs/JBSuckerDeployerConfig.sol";
@@ -29,27 +36,40 @@ import {IJBAddressRegistry} from "@bananapus/address-registry-v6/src/interfaces/
29
36
  import {JBBeforePayRecordedContext} from "@bananapus/core-v6/src/structs/JBBeforePayRecordedContext.sol";
30
37
  import {JBPayHookSpecification} from "@bananapus/core-v6/src/structs/JBPayHookSpecification.sol";
31
38
  import {JBTokenAmount} from "@bananapus/core-v6/src/structs/JBTokenAmount.sol";
39
+ import {REVEmpty721Config} from "./helpers/REVEmpty721Config.sol";
32
40
 
33
41
  /// @notice Regression tests for the empty buyback hook specifications fix.
34
42
  /// When JBBuybackHook determines minting is cheaper than swapping, it returns an empty
35
43
  /// hookSpecifications array. Before the fix, REVDeployer.beforePayRecordedWith would
36
44
  /// Panic(0x32) (array out-of-bounds) when accessing buybackHookSpecifications[0].
37
45
  contract TestEmptyBuybackSpecs is TestBaseWorkflow {
46
+ // forge-lint: disable-next-line(mixed-case-variable)
38
47
  bytes32 REV_DEPLOYER_SALT = "REVDeployer";
39
48
 
49
+ // forge-lint: disable-next-line(mixed-case-variable)
40
50
  REVDeployer REV_DEPLOYER;
51
+ // forge-lint: disable-next-line(mixed-case-variable)
41
52
  JB721TiersHook EXAMPLE_HOOK;
53
+ // forge-lint: disable-next-line(mixed-case-variable)
42
54
  IJB721TiersHookDeployer HOOK_DEPLOYER;
55
+ // forge-lint: disable-next-line(mixed-case-variable)
43
56
  IJB721TiersHookStore HOOK_STORE;
57
+ // forge-lint: disable-next-line(mixed-case-variable)
44
58
  IJBAddressRegistry ADDRESS_REGISTRY;
59
+ // forge-lint: disable-next-line(mixed-case-variable)
45
60
  IREVLoans LOANS_CONTRACT;
61
+ // forge-lint: disable-next-line(mixed-case-variable)
46
62
  IJBSuckerRegistry SUCKER_REGISTRY;
63
+ // forge-lint: disable-next-line(mixed-case-variable)
47
64
  CTPublisher PUBLISHER;
65
+ // forge-lint: disable-next-line(mixed-case-variable)
48
66
  MockBuybackDataHookMintPath MOCK_BUYBACK_MINT_PATH;
49
67
 
68
+ // forge-lint: disable-next-line(mixed-case-variable)
50
69
  uint256 FEE_PROJECT_ID;
51
70
 
52
71
  address private constant TRUSTED_FORWARDER = 0xB2b5841DBeF766d4b521221732F9B618fCf34A87;
72
+ // forge-lint: disable-next-line(mixed-case-variable)
53
73
  address USER = makeAddr("user");
54
74
 
55
75
  function setUp() public override {
@@ -57,8 +77,9 @@ contract TestEmptyBuybackSpecs is TestBaseWorkflow {
57
77
  FEE_PROJECT_ID = jbProjects().createFor(multisig());
58
78
  SUCKER_REGISTRY = new JBSuckerRegistry(jbDirectory(), jbPermissions(), multisig(), address(0));
59
79
  HOOK_STORE = new JB721TiersHookStore();
60
- EXAMPLE_HOOK =
61
- new JB721TiersHook(jbDirectory(), jbPermissions(), jbRulesets(), HOOK_STORE, jbSplits(), multisig());
80
+ EXAMPLE_HOOK = new JB721TiersHook(
81
+ jbDirectory(), jbPermissions(), jbPrices(), jbRulesets(), HOOK_STORE, jbSplits(), multisig()
82
+ );
62
83
  ADDRESS_REGISTRY = new JBAddressRegistry();
63
84
  HOOK_DEPLOYER = new JB721TiersHookDeployer(EXAMPLE_HOOK, HOOK_STORE, ADDRESS_REGISTRY, multisig());
64
85
  PUBLISHER = new CTPublisher(jbDirectory(), jbPermissions(), FEE_PROJECT_ID, multisig());
@@ -114,6 +135,7 @@ contract TestEmptyBuybackSpecs is TestBaseWorkflow {
114
135
  });
115
136
 
116
137
  cfg = REVConfig({
138
+ // forge-lint: disable-next-line(named-struct-fields)
117
139
  description: REVDescription("Test", "TST", "ipfs://test", "TEST_SALT"),
118
140
  baseCurrency: uint32(uint160(JBConstants.NATIVE_TOKEN)),
119
141
  splitOperator: multisig(),
@@ -134,15 +156,23 @@ contract TestEmptyBuybackSpecs is TestBaseWorkflow {
134
156
  revnetId: FEE_PROJECT_ID,
135
157
  configuration: feeCfg,
136
158
  terminalConfigurations: feeTc,
137
- suckerDeploymentConfiguration: feeSdc
159
+ suckerDeploymentConfiguration: feeSdc,
160
+ tiered721HookConfiguration: REVEmpty721Config.empty721Config(uint32(uint160(JBConstants.NATIVE_TOKEN))),
161
+ allowedPosts: REVEmpty721Config.emptyAllowedPosts()
138
162
  });
139
163
 
140
164
  (REVConfig memory cfg, JBTerminalConfig[] memory tc, REVSuckerDeploymentConfig memory sdc) =
141
165
  _buildMinimalConfig();
166
+ // forge-lint: disable-next-line(named-struct-fields)
142
167
  cfg.description = REVDescription("Test2", "TS2", "ipfs://test2", "TEST_SALT_2");
143
168
 
144
- revnetId = REV_DEPLOYER.deployFor({
145
- revnetId: 0, configuration: cfg, terminalConfigurations: tc, suckerDeploymentConfiguration: sdc
169
+ (revnetId,) = REV_DEPLOYER.deployFor({
170
+ revnetId: 0,
171
+ configuration: cfg,
172
+ terminalConfigurations: tc,
173
+ suckerDeploymentConfiguration: sdc,
174
+ tiered721HookConfiguration: REVEmpty721Config.empty721Config(uint32(uint160(JBConstants.NATIVE_TOKEN))),
175
+ allowedPosts: REVEmpty721Config.emptyAllowedPosts()
146
176
  });
147
177
  }
148
178
 
@@ -209,8 +239,8 @@ contract TestEmptyBuybackSpecs is TestBaseWorkflow {
209
239
  }
210
240
  }
211
241
 
212
- /// @notice Verify beforePayRecordedWith returns empty hookSpecifications when buyback returns empty.
213
- function test_beforePayRecordedWith_emptyBuybackSpecs_returnsEmptyArray() public {
242
+ /// @notice Verify beforePayRecordedWith returns only the 721 hook spec when buyback returns empty.
243
+ function test_beforePayRecordedWith_emptyBuybackSpecs_returnsOnly721Hook() public {
214
244
  uint256 revnetId = _deployFeeAndRevnet();
215
245
 
216
246
  JBBeforePayRecordedContext memory context = JBBeforePayRecordedContext({
@@ -233,6 +263,11 @@ contract TestEmptyBuybackSpecs is TestBaseWorkflow {
233
263
  (uint256 weight, JBPayHookSpecification[] memory specs) = REV_DEPLOYER.beforePayRecordedWith(context);
234
264
 
235
265
  assertEq(weight, context.weight, "Weight should pass through from buyback hook");
236
- assertEq(specs.length, 0, "Should return empty specs when buyback hook returns empty and no 721 hook");
266
+ assertEq(specs.length, 1, "Should return only the 721 hook spec when buyback hook returns empty");
267
+ assertEq(
268
+ address(specs[0].hook),
269
+ address(REV_DEPLOYER.tiered721HookOf(revnetId)),
270
+ "Spec hook should be the revnet's 721 hook"
271
+ );
237
272
  }
238
273
  }
@@ -1,23 +1,32 @@
1
1
  // SPDX-License-Identifier: MIT
2
2
  pragma solidity 0.8.26;
3
3
 
4
+ // forge-lint: disable-next-line(unaliased-plain-import)
4
5
  import "forge-std/Test.sol";
6
+ // forge-lint: disable-next-line(unaliased-plain-import)
5
7
  import /* {*} from */ "@bananapus/core-v6/test/helpers/TestBaseWorkflow.sol";
6
- import /* {*} from "@bananapus/721-hook-v6/src/JB721TiersHookDeployer.sol";
8
+ // import /* {*} from "@bananapus/721-hook-v6/src/JB721TiersHookDeployer.sol";
9
+ // forge-lint: disable-next-line(unaliased-plain-import)
7
10
  import /* {*} from */ "./../src/REVDeployer.sol";
11
+ // forge-lint: disable-next-line(unaliased-plain-import)
8
12
  import "@croptop/core-v6/src/CTPublisher.sol";
9
13
  import {MockBuybackDataHook} from "./mock/MockBuybackDataHook.sol";
14
+ import {REVEmpty721Config} from "./helpers/REVEmpty721Config.sol";
15
+ // forge-lint: disable-next-line(unaliased-plain-import)
10
16
  import "@bananapus/core-v6/script/helpers/CoreDeploymentLib.sol";
17
+ // forge-lint: disable-next-line(unaliased-plain-import)
11
18
  import "@bananapus/721-hook-v6/script/helpers/Hook721DeploymentLib.sol";
19
+ // forge-lint: disable-next-line(unaliased-plain-import)
12
20
  import "@bananapus/suckers-v6/script/helpers/SuckerDeploymentLib.sol";
21
+ // forge-lint: disable-next-line(unaliased-plain-import)
13
22
  import "@croptop/core-v6/script/helpers/CroptopDeploymentLib.sol";
23
+ // forge-lint: disable-next-line(unaliased-plain-import)
14
24
  import "@bananapus/router-terminal-v6/script/helpers/RouterTerminalDeploymentLib.sol";
15
25
  import {JBConstants} from "@bananapus/core-v6/src/libraries/JBConstants.sol";
16
26
  import {JBAccountingContext} from "@bananapus/core-v6/src/structs/JBAccountingContext.sol";
17
27
  import {MockPriceFeed} from "@bananapus/core-v6/test/mock/MockPriceFeed.sol";
18
28
  import {MockERC20} from "@bananapus/core-v6/test/mock/MockERC20.sol";
19
29
  import {REVLoans} from "../src/REVLoans.sol";
20
- import {REVLoan} from "../src/structs/REVLoan.sol";
21
30
  import {REVStageConfig, REVAutoIssuance} from "../src/structs/REVStageConfig.sol";
22
31
  import {REVLoanSource} from "../src/structs/REVLoanSource.sol";
23
32
  import {REVDescription} from "../src/structs/REVDescription.sol";
@@ -32,24 +41,40 @@ import {IJBAddressRegistry} from "@bananapus/address-registry-v6/src/interfaces/
32
41
 
33
42
  /// @notice Tests showing that flash loan surplus manipulation is economically unprofitable.
34
43
  contract TestFlashLoanSurplus is TestBaseWorkflow {
44
+ // forge-lint: disable-next-line(mixed-case-variable)
35
45
  bytes32 REV_DEPLOYER_SALT = "REVDeployer";
46
+ // forge-lint: disable-next-line(mixed-case-variable)
36
47
  bytes32 ERC20_SALT = "REV_TOKEN";
37
48
 
49
+ // forge-lint: disable-next-line(mixed-case-variable)
38
50
  REVDeployer REV_DEPLOYER;
51
+ // forge-lint: disable-next-line(mixed-case-variable)
39
52
  JB721TiersHook EXAMPLE_HOOK;
53
+ // forge-lint: disable-next-line(mixed-case-variable)
40
54
  IJB721TiersHookDeployer HOOK_DEPLOYER;
55
+ // forge-lint: disable-next-line(mixed-case-variable)
41
56
  IJB721TiersHookStore HOOK_STORE;
57
+ // forge-lint: disable-next-line(mixed-case-variable)
42
58
  IJBAddressRegistry ADDRESS_REGISTRY;
59
+ // forge-lint: disable-next-line(mixed-case-variable)
43
60
  IREVLoans LOANS_CONTRACT;
61
+ // forge-lint: disable-next-line(mixed-case-variable)
44
62
  MockERC20 TOKEN;
63
+ // forge-lint: disable-next-line(mixed-case-variable)
45
64
  IJBSuckerRegistry SUCKER_REGISTRY;
65
+ // forge-lint: disable-next-line(mixed-case-variable)
46
66
  CTPublisher PUBLISHER;
67
+ // forge-lint: disable-next-line(mixed-case-variable)
47
68
  MockBuybackDataHook MOCK_BUYBACK;
48
69
 
70
+ // forge-lint: disable-next-line(mixed-case-variable)
49
71
  uint256 FEE_PROJECT_ID;
72
+ // forge-lint: disable-next-line(mixed-case-variable)
50
73
  uint256 REVNET_ID;
51
74
 
75
+ // forge-lint: disable-next-line(mixed-case-variable)
52
76
  address USER = makeAddr("user");
77
+ // forge-lint: disable-next-line(mixed-case-variable)
53
78
  address ATTACKER = makeAddr("attacker");
54
79
 
55
80
  address private constant TRUSTED_FORWARDER = 0xB2b5841DBeF766d4b521221732F9B618fCf34A87;
@@ -59,8 +84,9 @@ contract TestFlashLoanSurplus is TestBaseWorkflow {
59
84
  FEE_PROJECT_ID = jbProjects().createFor(multisig());
60
85
  SUCKER_REGISTRY = new JBSuckerRegistry(jbDirectory(), jbPermissions(), multisig(), address(0));
61
86
  HOOK_STORE = new JB721TiersHookStore();
62
- EXAMPLE_HOOK =
63
- new JB721TiersHook(jbDirectory(), jbPermissions(), jbRulesets(), HOOK_STORE, jbSplits(), multisig());
87
+ EXAMPLE_HOOK = new JB721TiersHook(
88
+ jbDirectory(), jbPermissions(), jbPrices(), jbRulesets(), HOOK_STORE, jbSplits(), multisig()
89
+ );
64
90
  ADDRESS_REGISTRY = new JBAddressRegistry();
65
91
  HOOK_DEPLOYER = new JB721TiersHookDeployer(EXAMPLE_HOOK, HOOK_STORE, ADDRESS_REGISTRY, multisig());
66
92
  PUBLISHER = new CTPublisher(jbDirectory(), jbPermissions(), FEE_PROJECT_ID, multisig());
@@ -122,6 +148,7 @@ contract TestFlashLoanSurplus is TestBaseWorkflow {
122
148
  extraMetadata: 0
123
149
  });
124
150
  REVConfig memory cfg = REVConfig({
151
+ // forge-lint: disable-next-line(named-struct-fields)
125
152
  description: REVDescription("Revnet", "$REV", "ipfs://test", "REV_TOKEN"),
126
153
  baseCurrency: uint32(uint160(JBConstants.NATIVE_TOKEN)),
127
154
  splitOperator: multisig(),
@@ -134,7 +161,9 @@ contract TestFlashLoanSurplus is TestBaseWorkflow {
134
161
  terminalConfigurations: tc,
135
162
  suckerDeploymentConfiguration: REVSuckerDeploymentConfig({
136
163
  deployerConfigurations: new JBSuckerDeployerConfig[](0), salt: keccak256("FEE")
137
- })
164
+ }),
165
+ tiered721HookConfiguration: REVEmpty721Config.empty721Config(uint32(uint160(JBConstants.NATIVE_TOKEN))),
166
+ allowedPosts: REVEmpty721Config.emptyAllowedPosts()
138
167
  });
139
168
  }
140
169
 
@@ -166,18 +195,21 @@ contract TestFlashLoanSurplus is TestBaseWorkflow {
166
195
  REVLoanSource[] memory ls = new REVLoanSource[](1);
167
196
  ls[0] = REVLoanSource({token: JBConstants.NATIVE_TOKEN, terminal: jbMultiTerminal()});
168
197
  REVConfig memory cfg = REVConfig({
198
+ // forge-lint: disable-next-line(named-struct-fields)
169
199
  description: REVDescription("NANA", "$NANA", "ipfs://test2", "NANA_TOKEN"),
170
200
  baseCurrency: uint32(uint160(JBConstants.NATIVE_TOKEN)),
171
201
  splitOperator: multisig(),
172
202
  stageConfigurations: stages
173
203
  });
174
- REVNET_ID = REV_DEPLOYER.deployFor({
204
+ (REVNET_ID,) = REV_DEPLOYER.deployFor({
175
205
  revnetId: 0,
176
206
  configuration: cfg,
177
207
  terminalConfigurations: tc,
178
208
  suckerDeploymentConfiguration: REVSuckerDeploymentConfig({
179
209
  deployerConfigurations: new JBSuckerDeployerConfig[](0), salt: keccak256("NANA")
180
- })
210
+ }),
211
+ tiered721HookConfiguration: REVEmpty721Config.empty721Config(uint32(uint160(JBConstants.NATIVE_TOKEN))),
212
+ allowedPosts: REVEmpty721Config.emptyAllowedPosts()
181
213
  });
182
214
  }
183
215
 
@@ -1,22 +1,30 @@
1
1
  // SPDX-License-Identifier: MIT
2
2
  pragma solidity 0.8.26;
3
3
 
4
+ // forge-lint: disable-next-line(unaliased-plain-import)
4
5
  import "forge-std/Test.sol";
6
+ // forge-lint: disable-next-line(unaliased-plain-import)
5
7
  import /* {*} from */ "@bananapus/core-v6/test/helpers/TestBaseWorkflow.sol";
6
- import /* {*} from "@bananapus/721-hook-v6/src/JB721TiersHookDeployer.sol";
8
+ // import /* {*} from "@bananapus/721-hook-v6/src/JB721TiersHookDeployer.sol";
9
+ // forge-lint: disable-next-line(unaliased-plain-import)
7
10
  import /* {*} from */ "./../src/REVDeployer.sol";
11
+ // forge-lint: disable-next-line(unaliased-plain-import)
8
12
  import "@croptop/core-v6/src/CTPublisher.sol";
9
13
  import {MockBuybackDataHook} from "./mock/MockBuybackDataHook.sol";
14
+ // forge-lint: disable-next-line(unaliased-plain-import)
10
15
  import "@bananapus/core-v6/script/helpers/CoreDeploymentLib.sol";
16
+ // forge-lint: disable-next-line(unaliased-plain-import)
11
17
  import "@bananapus/721-hook-v6/script/helpers/Hook721DeploymentLib.sol";
18
+ // forge-lint: disable-next-line(unaliased-plain-import)
12
19
  import "@bananapus/suckers-v6/script/helpers/SuckerDeploymentLib.sol";
20
+ // forge-lint: disable-next-line(unaliased-plain-import)
13
21
  import "@croptop/core-v6/script/helpers/CroptopDeploymentLib.sol";
22
+ // forge-lint: disable-next-line(unaliased-plain-import)
14
23
  import "@bananapus/router-terminal-v6/script/helpers/RouterTerminalDeploymentLib.sol";
15
24
  import {JBConstants} from "@bananapus/core-v6/src/libraries/JBConstants.sol";
16
25
  import {JBAccountingContext} from "@bananapus/core-v6/src/structs/JBAccountingContext.sol";
17
26
  import {REVLoans} from "../src/REVLoans.sol";
18
27
  import {REVStageConfig, REVAutoIssuance} from "../src/structs/REVStageConfig.sol";
19
- import {REVLoanSource} from "../src/structs/REVLoanSource.sol";
20
28
  import {REVDescription} from "../src/structs/REVDescription.sol";
21
29
  import {IREVLoans} from "./../src/interfaces/IREVLoans.sol";
22
30
  import {JBSuckerDeployerConfig} from "@bananapus/suckers-v6/src/structs/JBSuckerDeployerConfig.sol";
@@ -29,7 +37,7 @@ import {IJBAddressRegistry} from "@bananapus/address-registry-v6/src/interfaces/
29
37
  import {JBBeforePayRecordedContext} from "@bananapus/core-v6/src/structs/JBBeforePayRecordedContext.sol";
30
38
  import {JBPayHookSpecification} from "@bananapus/core-v6/src/structs/JBPayHookSpecification.sol";
31
39
  import {JBTokenAmount} from "@bananapus/core-v6/src/structs/JBTokenAmount.sol";
32
- import {JBRuleset} from "@bananapus/core-v6/src/structs/JBRuleset.sol";
40
+ import {REVEmpty721Config} from "./helpers/REVEmpty721Config.sol";
33
41
 
34
42
  /// @notice Tests for PR #22: fix/c2-hook-array-oob
35
43
  /// Verifies that the fix for the hook array out-of-bounds bug works correctly.
@@ -37,21 +45,33 @@ import {JBRuleset} from "@bananapus/core-v6/src/structs/JBRuleset.sol";
37
45
  /// when there is no tiered 721 hook (array size is 1, not 2).
38
46
  /// The fix: `hookSpecifications[usesTiered721Hook ? 1 : 0] = buybackHookSpecifications[0]`.
39
47
  contract TestHookArrayOOB is TestBaseWorkflow {
48
+ // forge-lint: disable-next-line(mixed-case-variable)
40
49
  bytes32 REV_DEPLOYER_SALT = "REVDeployer";
41
50
 
51
+ // forge-lint: disable-next-line(mixed-case-variable)
42
52
  REVDeployer REV_DEPLOYER;
53
+ // forge-lint: disable-next-line(mixed-case-variable)
43
54
  JB721TiersHook EXAMPLE_HOOK;
55
+ // forge-lint: disable-next-line(mixed-case-variable)
44
56
  IJB721TiersHookDeployer HOOK_DEPLOYER;
57
+ // forge-lint: disable-next-line(mixed-case-variable)
45
58
  IJB721TiersHookStore HOOK_STORE;
59
+ // forge-lint: disable-next-line(mixed-case-variable)
46
60
  IJBAddressRegistry ADDRESS_REGISTRY;
61
+ // forge-lint: disable-next-line(mixed-case-variable)
47
62
  IREVLoans LOANS_CONTRACT;
63
+ // forge-lint: disable-next-line(mixed-case-variable)
48
64
  IJBSuckerRegistry SUCKER_REGISTRY;
65
+ // forge-lint: disable-next-line(mixed-case-variable)
49
66
  CTPublisher PUBLISHER;
67
+ // forge-lint: disable-next-line(mixed-case-variable)
50
68
  MockBuybackDataHook MOCK_BUYBACK;
51
69
 
70
+ // forge-lint: disable-next-line(mixed-case-variable)
52
71
  uint256 FEE_PROJECT_ID;
53
72
 
54
73
  address private constant TRUSTED_FORWARDER = 0xB2b5841DBeF766d4b521221732F9B618fCf34A87;
74
+ // forge-lint: disable-next-line(mixed-case-variable)
55
75
  address USER = makeAddr("user");
56
76
 
57
77
  function setUp() public override {
@@ -59,8 +79,9 @@ contract TestHookArrayOOB is TestBaseWorkflow {
59
79
  FEE_PROJECT_ID = jbProjects().createFor(multisig());
60
80
  SUCKER_REGISTRY = new JBSuckerRegistry(jbDirectory(), jbPermissions(), multisig(), address(0));
61
81
  HOOK_STORE = new JB721TiersHookStore();
62
- EXAMPLE_HOOK =
63
- new JB721TiersHook(jbDirectory(), jbPermissions(), jbRulesets(), HOOK_STORE, jbSplits(), multisig());
82
+ EXAMPLE_HOOK = new JB721TiersHook(
83
+ jbDirectory(), jbPermissions(), jbPrices(), jbRulesets(), HOOK_STORE, jbSplits(), multisig()
84
+ );
64
85
  ADDRESS_REGISTRY = new JBAddressRegistry();
65
86
  HOOK_DEPLOYER = new JB721TiersHookDeployer(EXAMPLE_HOOK, HOOK_STORE, ADDRESS_REGISTRY, multisig());
66
87
  PUBLISHER = new CTPublisher(jbDirectory(), jbPermissions(), FEE_PROJECT_ID, multisig());
@@ -117,6 +138,7 @@ contract TestHookArrayOOB is TestBaseWorkflow {
117
138
  });
118
139
 
119
140
  cfg = REVConfig({
141
+ // forge-lint: disable-next-line(named-struct-fields)
120
142
  description: REVDescription("Test", "TST", "ipfs://test", "TEST_SALT"),
121
143
  baseCurrency: uint32(uint160(JBConstants.NATIVE_TOKEN)),
122
144
  splitOperator: multisig(),
@@ -139,17 +161,25 @@ contract TestHookArrayOOB is TestBaseWorkflow {
139
161
  revnetId: FEE_PROJECT_ID,
140
162
  configuration: feeCfg,
141
163
  terminalConfigurations: feeTc,
142
- suckerDeploymentConfiguration: feeSdc
164
+ suckerDeploymentConfiguration: feeSdc,
165
+ tiered721HookConfiguration: REVEmpty721Config.empty721Config(uint32(uint160(JBConstants.NATIVE_TOKEN))),
166
+ allowedPosts: REVEmpty721Config.emptyAllowedPosts()
143
167
  });
144
168
 
145
169
  // Deploy a new test revnet (revnetId: 0 = create new)
146
170
  (REVConfig memory cfg, JBTerminalConfig[] memory tc, REVSuckerDeploymentConfig memory sdc) =
147
171
  _buildMinimalConfig();
148
172
  // Use a different salt so the ERC20 deploy doesn't clash
173
+ // forge-lint: disable-next-line(named-struct-fields)
149
174
  cfg.description = REVDescription("Test2", "TS2", "ipfs://test2", "TEST_SALT_2");
150
175
 
151
- revnetId = REV_DEPLOYER.deployFor({
152
- revnetId: 0, configuration: cfg, terminalConfigurations: tc, suckerDeploymentConfiguration: sdc
176
+ (revnetId,) = REV_DEPLOYER.deployFor({
177
+ revnetId: 0,
178
+ configuration: cfg,
179
+ terminalConfigurations: tc,
180
+ suckerDeploymentConfiguration: sdc,
181
+ tiered721HookConfiguration: REVEmpty721Config.empty721Config(uint32(uint160(JBConstants.NATIVE_TOKEN))),
182
+ allowedPosts: REVEmpty721Config.emptyAllowedPosts()
153
183
  });
154
184
  }
155
185
 
@@ -190,8 +220,8 @@ contract TestHookArrayOOB is TestBaseWorkflow {
190
220
  }
191
221
 
192
222
  /// @notice Test that beforePayRecordedWith returns correct hook specification counts.
193
- /// When no hooks are configured, should return empty array.
194
- function test_beforePayRecordedWith_noHooks_returnsEmptySpecs() public {
223
+ /// Every revnet now has both a buyback hook and a 721 hook.
224
+ function test_beforePayRecordedWith_returnsHookSpecs() public {
195
225
  uint256 revnetId = _deployFeeAndRevnet();
196
226
 
197
227
  // Build a mock context for beforePayRecordedWith
@@ -214,9 +244,8 @@ contract TestHookArrayOOB is TestBaseWorkflow {
214
244
 
215
245
  (uint256 weight, JBPayHookSpecification[] memory specs) = REV_DEPLOYER.beforePayRecordedWith(context);
216
246
 
217
- // With the global buyback hook but no 721 hook, weight should be the context weight
218
- // and specs should contain exactly the buyback hook specification.
247
+ // Every revnet has both the buyback hook and the 721 hook.
219
248
  assertEq(weight, context.weight, "Weight should be the default context weight");
220
- assertEq(specs.length, 1, "Should have exactly the buyback hook specification");
249
+ assertEq(specs.length, 2, "Should have buyback hook and 721 hook specifications");
221
250
  }
222
251
  }
@@ -1,16 +1,26 @@
1
1
  // SPDX-License-Identifier: MIT
2
2
  pragma solidity 0.8.26;
3
3
 
4
+ // forge-lint: disable-next-line(unaliased-plain-import)
4
5
  import "forge-std/Test.sol";
6
+ // forge-lint: disable-next-line(unaliased-plain-import)
5
7
  import /* {*} from */ "@bananapus/core-v6/test/helpers/TestBaseWorkflow.sol";
6
- import /* {*} from "@bananapus/721-hook-v6/src/JB721TiersHookDeployer.sol";
8
+ // import /* {*} from "@bananapus/721-hook-v6/src/JB721TiersHookDeployer.sol";
9
+ // forge-lint: disable-next-line(unaliased-plain-import)
7
10
  import /* {*} from */ "./../src/REVDeployer.sol";
11
+ // forge-lint: disable-next-line(unaliased-plain-import)
8
12
  import "@croptop/core-v6/src/CTPublisher.sol";
9
13
  import {MockBuybackDataHook} from "./mock/MockBuybackDataHook.sol";
14
+ import {REVEmpty721Config} from "./helpers/REVEmpty721Config.sol";
15
+ // forge-lint: disable-next-line(unaliased-plain-import)
10
16
  import "@bananapus/core-v6/script/helpers/CoreDeploymentLib.sol";
17
+ // forge-lint: disable-next-line(unaliased-plain-import)
11
18
  import "@bananapus/721-hook-v6/script/helpers/Hook721DeploymentLib.sol";
19
+ // forge-lint: disable-next-line(unaliased-plain-import)
12
20
  import "@bananapus/suckers-v6/script/helpers/SuckerDeploymentLib.sol";
21
+ // forge-lint: disable-next-line(unaliased-plain-import)
13
22
  import "@croptop/core-v6/script/helpers/CroptopDeploymentLib.sol";
23
+ // forge-lint: disable-next-line(unaliased-plain-import)
14
24
  import "@bananapus/router-terminal-v6/script/helpers/RouterTerminalDeploymentLib.sol";
15
25
  import {JBConstants} from "@bananapus/core-v6/src/libraries/JBConstants.sol";
16
26
  import {JBAccountingContext} from "@bananapus/core-v6/src/structs/JBAccountingContext.sol";
@@ -22,7 +32,6 @@ import {REVLoan} from "../src/structs/REVLoan.sol";
22
32
  import {REVStageConfig, REVAutoIssuance} from "../src/structs/REVStageConfig.sol";
23
33
  import {REVLoanSource} from "../src/structs/REVLoanSource.sol";
24
34
  import {REVDescription} from "../src/structs/REVDescription.sol";
25
- import {IREVLoans} from "./../src/interfaces/IREVLoans.sol";
26
35
  import {JBSuckerDeployerConfig} from "@bananapus/suckers-v6/src/structs/JBSuckerDeployerConfig.sol";
27
36
  import {JBSuckerRegistry} from "@bananapus/suckers-v6/src/JBSuckerRegistry.sol";
28
37
  import {JB721TiersHookDeployer} from "@bananapus/721-hook-v6/src/JB721TiersHookDeployer.sol";
@@ -34,22 +43,36 @@ import {IERC721} from "@openzeppelin/contracts/token/ERC721/IERC721.sol";
34
43
 
35
44
  /// @notice Tests for PR #10: liquidation behavior documentation and collateral burn mechanics.
36
45
  contract TestLiquidationBehavior is TestBaseWorkflow {
46
+ // forge-lint: disable-next-line(mixed-case-variable)
37
47
  bytes32 REV_DEPLOYER_SALT = "REVDeployer";
38
48
 
49
+ // forge-lint: disable-next-line(mixed-case-variable)
39
50
  REVDeployer REV_DEPLOYER;
51
+ // forge-lint: disable-next-line(mixed-case-variable)
40
52
  JB721TiersHook EXAMPLE_HOOK;
53
+ // forge-lint: disable-next-line(mixed-case-variable)
41
54
  IJB721TiersHookDeployer HOOK_DEPLOYER;
55
+ // forge-lint: disable-next-line(mixed-case-variable)
42
56
  IJB721TiersHookStore HOOK_STORE;
57
+ // forge-lint: disable-next-line(mixed-case-variable)
43
58
  IJBAddressRegistry ADDRESS_REGISTRY;
59
+ // forge-lint: disable-next-line(mixed-case-variable)
44
60
  REVLoans LOANS_CONTRACT;
61
+ // forge-lint: disable-next-line(mixed-case-variable)
45
62
  MockERC20 TOKEN;
63
+ // forge-lint: disable-next-line(mixed-case-variable)
46
64
  IJBSuckerRegistry SUCKER_REGISTRY;
65
+ // forge-lint: disable-next-line(mixed-case-variable)
47
66
  CTPublisher PUBLISHER;
67
+ // forge-lint: disable-next-line(mixed-case-variable)
48
68
  MockBuybackDataHook MOCK_BUYBACK;
49
69
 
70
+ // forge-lint: disable-next-line(mixed-case-variable)
50
71
  uint256 FEE_PROJECT_ID;
72
+ // forge-lint: disable-next-line(mixed-case-variable)
51
73
  uint256 REVNET_ID;
52
74
 
75
+ // forge-lint: disable-next-line(mixed-case-variable)
53
76
  address USER = makeAddr("user");
54
77
 
55
78
  address private constant TRUSTED_FORWARDER = 0xB2b5841DBeF766d4b521221732F9B618fCf34A87;
@@ -59,8 +82,9 @@ contract TestLiquidationBehavior is TestBaseWorkflow {
59
82
  FEE_PROJECT_ID = jbProjects().createFor(multisig());
60
83
  SUCKER_REGISTRY = new JBSuckerRegistry(jbDirectory(), jbPermissions(), multisig(), address(0));
61
84
  HOOK_STORE = new JB721TiersHookStore();
62
- EXAMPLE_HOOK =
63
- new JB721TiersHook(jbDirectory(), jbPermissions(), jbRulesets(), HOOK_STORE, jbSplits(), multisig());
85
+ EXAMPLE_HOOK = new JB721TiersHook(
86
+ jbDirectory(), jbPermissions(), jbPrices(), jbRulesets(), HOOK_STORE, jbSplits(), multisig()
87
+ );
64
88
  ADDRESS_REGISTRY = new JBAddressRegistry();
65
89
  HOOK_DEPLOYER = new JB721TiersHookDeployer(EXAMPLE_HOOK, HOOK_STORE, ADDRESS_REGISTRY, multisig());
66
90
  PUBLISHER = new CTPublisher(jbDirectory(), jbPermissions(), FEE_PROJECT_ID, multisig());
@@ -121,6 +145,7 @@ contract TestLiquidationBehavior is TestBaseWorkflow {
121
145
  extraMetadata: 0
122
146
  });
123
147
  REVConfig memory cfg = REVConfig({
148
+ // forge-lint: disable-next-line(named-struct-fields)
124
149
  description: REVDescription("Revnet", "$REV", "ipfs://test", "REV_TOKEN"),
125
150
  baseCurrency: uint32(uint160(JBConstants.NATIVE_TOKEN)),
126
151
  splitOperator: multisig(),
@@ -133,7 +158,9 @@ contract TestLiquidationBehavior is TestBaseWorkflow {
133
158
  terminalConfigurations: tc,
134
159
  suckerDeploymentConfiguration: REVSuckerDeploymentConfig({
135
160
  deployerConfigurations: new JBSuckerDeployerConfig[](0), salt: keccak256("FEE")
136
- })
161
+ }),
162
+ tiered721HookConfiguration: REVEmpty721Config.empty721Config(uint32(uint160(JBConstants.NATIVE_TOKEN))),
163
+ allowedPosts: REVEmpty721Config.emptyAllowedPosts()
137
164
  });
138
165
  }
139
166
 
@@ -165,18 +192,21 @@ contract TestLiquidationBehavior is TestBaseWorkflow {
165
192
  REVLoanSource[] memory ls = new REVLoanSource[](1);
166
193
  ls[0] = REVLoanSource({token: JBConstants.NATIVE_TOKEN, terminal: jbMultiTerminal()});
167
194
  REVConfig memory cfg = REVConfig({
195
+ // forge-lint: disable-next-line(named-struct-fields)
168
196
  description: REVDescription("NANA", "$NANA", "ipfs://test2", "NANA_TOKEN"),
169
197
  baseCurrency: uint32(uint160(JBConstants.NATIVE_TOKEN)),
170
198
  splitOperator: multisig(),
171
199
  stageConfigurations: stages
172
200
  });
173
- REVNET_ID = REV_DEPLOYER.deployFor({
201
+ (REVNET_ID,) = REV_DEPLOYER.deployFor({
174
202
  revnetId: 0,
175
203
  configuration: cfg,
176
204
  terminalConfigurations: tc,
177
205
  suckerDeploymentConfiguration: REVSuckerDeploymentConfig({
178
206
  deployerConfigurations: new JBSuckerDeployerConfig[](0), salt: keccak256("NANA")
179
- })
207
+ }),
208
+ tiered721HookConfiguration: REVEmpty721Config.empty721Config(uint32(uint160(JBConstants.NATIVE_TOKEN))),
209
+ allowedPosts: REVEmpty721Config.emptyAllowedPosts()
180
210
  });
181
211
  }
182
212