@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,23 +1,31 @@
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 {JBPermissionIds} from "@bananapus/permission-ids-v6/src/JBPermissionIds.sol";
18
27
  import {REVLoans} from "../src/REVLoans.sol";
19
28
  import {REVStageConfig, REVAutoIssuance} from "../src/structs/REVStageConfig.sol";
20
- import {REVLoanSource} from "../src/structs/REVLoanSource.sol";
21
29
  import {REVDescription} from "../src/structs/REVDescription.sol";
22
30
  import {IREVLoans} from "./../src/interfaces/IREVLoans.sol";
23
31
  import {JBSuckerDeployerConfig} from "@bananapus/suckers-v6/src/structs/JBSuckerDeployerConfig.sol";
@@ -27,23 +35,36 @@ import {JB721TiersHook} from "@bananapus/721-hook-v6/src/JB721TiersHook.sol";
27
35
  import {JB721TiersHookStore} from "@bananapus/721-hook-v6/src/JB721TiersHookStore.sol";
28
36
  import {JBAddressRegistry} from "@bananapus/address-registry-v6/src/JBAddressRegistry.sol";
29
37
  import {IJBAddressRegistry} from "@bananapus/address-registry-v6/src/interfaces/IJBAddressRegistry.sol";
38
+ import {REVEmpty721Config} from "./helpers/REVEmpty721Config.sol";
30
39
 
31
40
  /// @notice Tests for default operator permissions including SET_ROUTER_TERMINAL.
32
41
  /// Verifies that all default split operator permissions are granted correctly.
33
42
  contract TestSwapTerminalPermission is TestBaseWorkflow {
43
+ // forge-lint: disable-next-line(mixed-case-variable)
34
44
  bytes32 REV_DEPLOYER_SALT = "REVDeployer";
35
45
 
46
+ // forge-lint: disable-next-line(mixed-case-variable)
36
47
  REVDeployer REV_DEPLOYER;
48
+ // forge-lint: disable-next-line(mixed-case-variable)
37
49
  JB721TiersHook EXAMPLE_HOOK;
50
+ // forge-lint: disable-next-line(mixed-case-variable)
38
51
  IJB721TiersHookDeployer HOOK_DEPLOYER;
52
+ // forge-lint: disable-next-line(mixed-case-variable)
39
53
  IJB721TiersHookStore HOOK_STORE;
54
+ // forge-lint: disable-next-line(mixed-case-variable)
40
55
  IJBAddressRegistry ADDRESS_REGISTRY;
56
+ // forge-lint: disable-next-line(mixed-case-variable)
41
57
  IREVLoans LOANS_CONTRACT;
58
+ // forge-lint: disable-next-line(mixed-case-variable)
42
59
  IJBSuckerRegistry SUCKER_REGISTRY;
60
+ // forge-lint: disable-next-line(mixed-case-variable)
43
61
  CTPublisher PUBLISHER;
62
+ // forge-lint: disable-next-line(mixed-case-variable)
44
63
  MockBuybackDataHook MOCK_BUYBACK;
45
64
 
65
+ // forge-lint: disable-next-line(mixed-case-variable)
46
66
  uint256 FEE_PROJECT_ID;
67
+ // forge-lint: disable-next-line(mixed-case-variable)
47
68
  uint256 TEST_REVNET_ID;
48
69
 
49
70
  address private constant TRUSTED_FORWARDER = 0xB2b5841DBeF766d4b521221732F9B618fCf34A87;
@@ -53,8 +74,9 @@ contract TestSwapTerminalPermission is TestBaseWorkflow {
53
74
  FEE_PROJECT_ID = jbProjects().createFor(multisig());
54
75
  SUCKER_REGISTRY = new JBSuckerRegistry(jbDirectory(), jbPermissions(), multisig(), address(0));
55
76
  HOOK_STORE = new JB721TiersHookStore();
56
- EXAMPLE_HOOK =
57
- new JB721TiersHook(jbDirectory(), jbPermissions(), jbRulesets(), HOOK_STORE, jbSplits(), multisig());
77
+ EXAMPLE_HOOK = new JB721TiersHook(
78
+ jbDirectory(), jbPermissions(), jbPrices(), jbRulesets(), HOOK_STORE, jbSplits(), multisig()
79
+ );
58
80
  ADDRESS_REGISTRY = new JBAddressRegistry();
59
81
  HOOK_DEPLOYER = new JB721TiersHookDeployer(EXAMPLE_HOOK, HOOK_STORE, ADDRESS_REGISTRY, multisig());
60
82
  PUBLISHER = new CTPublisher(jbDirectory(), jbPermissions(), FEE_PROJECT_ID, multisig());
@@ -89,15 +111,22 @@ contract TestSwapTerminalPermission is TestBaseWorkflow {
89
111
  revnetId: FEE_PROJECT_ID,
90
112
  configuration: feeCfg,
91
113
  terminalConfigurations: feeTc,
92
- suckerDeploymentConfiguration: feeSdc
114
+ suckerDeploymentConfiguration: feeSdc,
115
+ tiered721HookConfiguration: REVEmpty721Config.empty721Config(uint32(uint160(JBConstants.NATIVE_TOKEN))),
116
+ allowedPosts: REVEmpty721Config.emptyAllowedPosts()
93
117
  });
94
118
 
95
119
  // Deploy the test revnet
96
120
  (REVConfig memory cfg, JBTerminalConfig[] memory tc, REVSuckerDeploymentConfig memory sdc) =
97
121
  _buildConfig("TestRevnet", "TST", "TST_SALT");
98
122
 
99
- TEST_REVNET_ID = REV_DEPLOYER.deployFor({
100
- revnetId: 0, configuration: cfg, terminalConfigurations: tc, suckerDeploymentConfiguration: sdc
123
+ (TEST_REVNET_ID,) = REV_DEPLOYER.deployFor({
124
+ revnetId: 0,
125
+ configuration: cfg,
126
+ terminalConfigurations: tc,
127
+ suckerDeploymentConfiguration: sdc,
128
+ tiered721HookConfiguration: REVEmpty721Config.empty721Config(uint32(uint160(JBConstants.NATIVE_TOKEN))),
129
+ allowedPosts: REVEmpty721Config.emptyAllowedPosts()
101
130
  });
102
131
  }
103
132
 
@@ -134,6 +163,7 @@ contract TestSwapTerminalPermission is TestBaseWorkflow {
134
163
  });
135
164
 
136
165
  cfg = REVConfig({
166
+ // forge-lint: disable-next-line(named-struct-fields)
137
167
  description: REVDescription(name, ticker, "ipfs://test", salt),
138
168
  baseCurrency: uint32(uint160(JBConstants.NATIVE_TOKEN)),
139
169
  splitOperator: multisig(),
@@ -1,17 +1,27 @@
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";
10
15
 
16
+ // forge-lint: disable-next-line(unaliased-plain-import)
11
17
  import "@bananapus/core-v6/script/helpers/CoreDeploymentLib.sol";
18
+ // forge-lint: disable-next-line(unaliased-plain-import)
12
19
  import "@bananapus/721-hook-v6/script/helpers/Hook721DeploymentLib.sol";
20
+ // forge-lint: disable-next-line(unaliased-plain-import)
13
21
  import "@bananapus/suckers-v6/script/helpers/SuckerDeploymentLib.sol";
22
+ // forge-lint: disable-next-line(unaliased-plain-import)
14
23
  import "@croptop/core-v6/script/helpers/CroptopDeploymentLib.sol";
24
+ // forge-lint: disable-next-line(unaliased-plain-import)
15
25
  import "@bananapus/router-terminal-v6/script/helpers/RouterTerminalDeploymentLib.sol";
16
26
  import {JBConstants} from "@bananapus/core-v6/src/libraries/JBConstants.sol";
17
27
  import {JBAccountingContext} from "@bananapus/core-v6/src/structs/JBAccountingContext.sol";
@@ -34,23 +44,38 @@ import {IJBAddressRegistry} from "@bananapus/address-registry-v6/src/interfaces/
34
44
  /// @title TestUint112Overflow
35
45
  /// @notice Tests for uint112 truncation fix in REVLoans._adjust()
36
46
  contract TestUint112Overflow is TestBaseWorkflow {
47
+ // forge-lint: disable-next-line(mixed-case-variable)
37
48
  bytes32 REV_DEPLOYER_SALT = "REVDeployer";
49
+ // forge-lint: disable-next-line(mixed-case-variable)
38
50
  bytes32 ERC20_SALT = "REV_TOKEN";
39
51
 
52
+ // forge-lint: disable-next-line(mixed-case-variable)
40
53
  REVDeployer REV_DEPLOYER;
54
+ // forge-lint: disable-next-line(mixed-case-variable)
41
55
  JB721TiersHook EXAMPLE_HOOK;
56
+ // forge-lint: disable-next-line(mixed-case-variable)
42
57
  IJB721TiersHookDeployer HOOK_DEPLOYER;
58
+ // forge-lint: disable-next-line(mixed-case-variable)
43
59
  IJB721TiersHookStore HOOK_STORE;
60
+ // forge-lint: disable-next-line(mixed-case-variable)
44
61
  IJBAddressRegistry ADDRESS_REGISTRY;
62
+ // forge-lint: disable-next-line(mixed-case-variable)
45
63
  IREVLoans LOANS_CONTRACT;
64
+ // forge-lint: disable-next-line(mixed-case-variable)
46
65
  MockERC20 TOKEN;
66
+ // forge-lint: disable-next-line(mixed-case-variable)
47
67
  IJBSuckerRegistry SUCKER_REGISTRY;
68
+ // forge-lint: disable-next-line(mixed-case-variable)
48
69
  CTPublisher PUBLISHER;
70
+ // forge-lint: disable-next-line(mixed-case-variable)
49
71
  MockBuybackDataHook MOCK_BUYBACK;
50
72
 
73
+ // forge-lint: disable-next-line(mixed-case-variable)
51
74
  uint256 FEE_PROJECT_ID;
75
+ // forge-lint: disable-next-line(mixed-case-variable)
52
76
  uint256 REVNET_ID;
53
77
 
78
+ // forge-lint: disable-next-line(mixed-case-variable)
54
79
  address USER = makeAddr("user");
55
80
  address private constant TRUSTED_FORWARDER = 0xB2b5841DBeF766d4b521221732F9B618fCf34A87;
56
81
 
@@ -61,8 +86,9 @@ contract TestUint112Overflow is TestBaseWorkflow {
61
86
 
62
87
  SUCKER_REGISTRY = new JBSuckerRegistry(jbDirectory(), jbPermissions(), multisig(), address(0));
63
88
  HOOK_STORE = new JB721TiersHookStore();
64
- EXAMPLE_HOOK =
65
- new JB721TiersHook(jbDirectory(), jbPermissions(), jbRulesets(), HOOK_STORE, jbSplits(), multisig());
89
+ EXAMPLE_HOOK = new JB721TiersHook(
90
+ jbDirectory(), jbPermissions(), jbPrices(), jbRulesets(), HOOK_STORE, jbSplits(), multisig()
91
+ );
66
92
  ADDRESS_REGISTRY = new JBAddressRegistry();
67
93
  HOOK_DEPLOYER = new JB721TiersHookDeployer(EXAMPLE_HOOK, HOOK_STORE, ADDRESS_REGISTRY, multisig());
68
94
  PUBLISHER = new CTPublisher(jbDirectory(), jbPermissions(), FEE_PROJECT_ID, multisig());
@@ -132,6 +158,7 @@ contract TestUint112Overflow is TestBaseWorkflow {
132
158
  });
133
159
 
134
160
  REVConfig memory cfg = REVConfig({
161
+ // forge-lint: disable-next-line(named-struct-fields)
135
162
  description: REVDescription("Revnet", "$REV", "ipfs://test", ERC20_SALT),
136
163
  baseCurrency: uint32(uint160(JBConstants.NATIVE_TOKEN)),
137
164
  splitOperator: multisig(),
@@ -144,7 +171,9 @@ contract TestUint112Overflow is TestBaseWorkflow {
144
171
  terminalConfigurations: tc,
145
172
  suckerDeploymentConfiguration: REVSuckerDeploymentConfig({
146
173
  deployerConfigurations: new JBSuckerDeployerConfig[](0), salt: keccak256("FEE")
147
- })
174
+ }),
175
+ tiered721HookConfiguration: REVEmpty721Config.empty721Config(uint32(uint160(JBConstants.NATIVE_TOKEN))),
176
+ allowedPosts: REVEmpty721Config.emptyAllowedPosts()
148
177
  });
149
178
  }
150
179
 
@@ -179,18 +208,21 @@ contract TestUint112Overflow is TestBaseWorkflow {
179
208
  ls[0] = REVLoanSource({token: JBConstants.NATIVE_TOKEN, terminal: jbMultiTerminal()});
180
209
 
181
210
  REVConfig memory cfg = REVConfig({
211
+ // forge-lint: disable-next-line(named-struct-fields)
182
212
  description: REVDescription("NANA", "$NANA", "ipfs://test2", "NANA_TOKEN"),
183
213
  baseCurrency: uint32(uint160(JBConstants.NATIVE_TOKEN)),
184
214
  splitOperator: multisig(),
185
215
  stageConfigurations: stages
186
216
  });
187
- REVNET_ID = REV_DEPLOYER.deployFor({
217
+ (REVNET_ID,) = REV_DEPLOYER.deployFor({
188
218
  revnetId: 0,
189
219
  configuration: cfg,
190
220
  terminalConfigurations: tc,
191
221
  suckerDeploymentConfiguration: REVSuckerDeploymentConfig({
192
222
  deployerConfigurations: new JBSuckerDeployerConfig[](0), salt: keccak256("NANA")
193
- })
223
+ }),
224
+ tiered721HookConfiguration: REVEmpty721Config.empty721Config(uint32(uint160(JBConstants.NATIVE_TOKEN))),
225
+ allowedPosts: REVEmpty721Config.emptyAllowedPosts()
194
226
  });
195
227
  }
196
228
 
@@ -237,6 +269,7 @@ contract TestUint112Overflow is TestBaseWorkflow {
237
269
  // uint112.max is the boundary — the check is `>`, not `>=`
238
270
  // So exactly uint112.max should NOT revert
239
271
  uint256 maxVal = type(uint112).max;
272
+ // forge-lint: disable-next-line(unsafe-typecast)
240
273
  uint112 casted = uint112(maxVal);
241
274
  assertEq(uint256(casted), maxVal, "Casting uint112.max should not truncate");
242
275
  }
@@ -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";
@@ -33,22 +43,36 @@ import {IJBAddressRegistry} from "@bananapus/address-registry-v6/src/interfaces/
33
43
 
34
44
  /// @notice Tests for PR #16: zero repayment prevention.
35
45
  contract TestZeroRepayment is TestBaseWorkflow {
46
+ // forge-lint: disable-next-line(mixed-case-variable)
36
47
  bytes32 REV_DEPLOYER_SALT = "REVDeployer";
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");
53
77
 
54
78
  address private constant TRUSTED_FORWARDER = 0xB2b5841DBeF766d4b521221732F9B618fCf34A87;
@@ -58,8 +82,9 @@ contract TestZeroRepayment is TestBaseWorkflow {
58
82
  FEE_PROJECT_ID = jbProjects().createFor(multisig());
59
83
  SUCKER_REGISTRY = new JBSuckerRegistry(jbDirectory(), jbPermissions(), multisig(), address(0));
60
84
  HOOK_STORE = new JB721TiersHookStore();
61
- EXAMPLE_HOOK =
62
- new JB721TiersHook(jbDirectory(), jbPermissions(), jbRulesets(), HOOK_STORE, jbSplits(), multisig());
85
+ EXAMPLE_HOOK = new JB721TiersHook(
86
+ jbDirectory(), jbPermissions(), jbPrices(), jbRulesets(), HOOK_STORE, jbSplits(), multisig()
87
+ );
63
88
  ADDRESS_REGISTRY = new JBAddressRegistry();
64
89
  HOOK_DEPLOYER = new JB721TiersHookDeployer(EXAMPLE_HOOK, HOOK_STORE, ADDRESS_REGISTRY, multisig());
65
90
  PUBLISHER = new CTPublisher(jbDirectory(), jbPermissions(), FEE_PROJECT_ID, multisig());
@@ -120,6 +145,7 @@ contract TestZeroRepayment is TestBaseWorkflow {
120
145
  extraMetadata: 0
121
146
  });
122
147
  REVConfig memory cfg = REVConfig({
148
+ // forge-lint: disable-next-line(named-struct-fields)
123
149
  description: REVDescription("Revnet", "$REV", "ipfs://test", "REV_TOKEN"),
124
150
  baseCurrency: uint32(uint160(JBConstants.NATIVE_TOKEN)),
125
151
  splitOperator: multisig(),
@@ -132,7 +158,9 @@ contract TestZeroRepayment is TestBaseWorkflow {
132
158
  terminalConfigurations: tc,
133
159
  suckerDeploymentConfiguration: REVSuckerDeploymentConfig({
134
160
  deployerConfigurations: new JBSuckerDeployerConfig[](0), salt: keccak256("FEE")
135
- })
161
+ }),
162
+ tiered721HookConfiguration: REVEmpty721Config.empty721Config(uint32(uint160(JBConstants.NATIVE_TOKEN))),
163
+ allowedPosts: REVEmpty721Config.emptyAllowedPosts()
136
164
  });
137
165
  }
138
166
 
@@ -164,18 +192,21 @@ contract TestZeroRepayment is TestBaseWorkflow {
164
192
  REVLoanSource[] memory ls = new REVLoanSource[](1);
165
193
  ls[0] = REVLoanSource({token: JBConstants.NATIVE_TOKEN, terminal: jbMultiTerminal()});
166
194
  REVConfig memory cfg = REVConfig({
195
+ // forge-lint: disable-next-line(named-struct-fields)
167
196
  description: REVDescription("NANA", "$NANA", "ipfs://test2", "NANA_TOKEN"),
168
197
  baseCurrency: uint32(uint160(JBConstants.NATIVE_TOKEN)),
169
198
  splitOperator: multisig(),
170
199
  stageConfigurations: stages
171
200
  });
172
- REVNET_ID = REV_DEPLOYER.deployFor({
201
+ (REVNET_ID,) = REV_DEPLOYER.deployFor({
173
202
  revnetId: 0,
174
203
  configuration: cfg,
175
204
  terminalConfigurations: tc,
176
205
  suckerDeploymentConfiguration: REVSuckerDeploymentConfig({
177
206
  deployerConfigurations: new JBSuckerDeployerConfig[](0), salt: keccak256("NANA")
178
- })
207
+ }),
208
+ tiered721HookConfiguration: REVEmpty721Config.empty721Config(uint32(uint160(JBConstants.NATIVE_TOKEN))),
209
+ allowedPosts: REVEmpty721Config.emptyAllowedPosts()
179
210
  });
180
211
  }
181
212
 
@@ -1,14 +1,23 @@
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";
12
+ // forge-lint: disable-next-line(unaliased-plain-import)
8
13
  import "@bananapus/core-v6/script/helpers/CoreDeploymentLib.sol";
14
+ // forge-lint: disable-next-line(unaliased-plain-import)
9
15
  import "@bananapus/721-hook-v6/script/helpers/Hook721DeploymentLib.sol";
16
+ // forge-lint: disable-next-line(unaliased-plain-import)
10
17
  import "@bananapus/suckers-v6/script/helpers/SuckerDeploymentLib.sol";
18
+ // forge-lint: disable-next-line(unaliased-plain-import)
11
19
  import "@croptop/core-v6/script/helpers/CroptopDeploymentLib.sol";
20
+ // forge-lint: disable-next-line(unaliased-plain-import)
12
21
  import "@bananapus/router-terminal-v6/script/helpers/RouterTerminalDeploymentLib.sol";
13
22
 
14
23
  import {JBConstants} from "@bananapus/core-v6/src/libraries/JBConstants.sol";
@@ -29,6 +38,7 @@ import {JBAddressRegistry} from "@bananapus/address-registry-v6/src/JBAddressReg
29
38
  import {IJBAddressRegistry} from "@bananapus/address-registry-v6/src/interfaces/IJBAddressRegistry.sol";
30
39
  import {IJBRulesetDataHook} from "@bananapus/core-v6/src/interfaces/IJBRulesetDataHook.sol";
31
40
  import {IJBBuybackHookRegistry} from "@bananapus/buyback-hook-v6/src/interfaces/IJBBuybackHookRegistry.sol";
41
+ // forge-lint: disable-next-line(unused-import)
32
42
  import {IJBPayHook} from "@bananapus/core-v6/src/interfaces/IJBPayHook.sol";
33
43
  import {JB721TierConfig} from "@bananapus/721-hook-v6/src/structs/JB721TierConfig.sol";
34
44
  import {JB721InitTiersConfig} from "@bananapus/721-hook-v6/src/structs/JB721InitTiersConfig.sol";
@@ -37,10 +47,12 @@ import {REVDeploy721TiersHookConfig} from "../../src/structs/REVDeploy721TiersHo
37
47
  import {REVBaseline721HookConfig} from "../../src/structs/REVBaseline721HookConfig.sol";
38
48
  import {REV721TiersHookFlags} from "../../src/structs/REV721TiersHookFlags.sol";
39
49
  import {REVCroptopAllowedPost} from "../../src/structs/REVCroptopAllowedPost.sol";
50
+ import {REVEmpty721Config} from "../helpers/REVEmpty721Config.sol";
40
51
 
41
52
  // Buyback hook
42
53
  import {JBBuybackHook} from "@bananapus/buyback-hook-v6/src/JBBuybackHook.sol";
43
54
  import {JBBuybackHookRegistry} from "@bananapus/buyback-hook-v6/src/JBBuybackHookRegistry.sol";
55
+ // forge-lint: disable-next-line(unused-import)
44
56
  import {IJBBuybackHook} from "@bananapus/buyback-hook-v6/src/interfaces/IJBBuybackHook.sol";
45
57
  import {IGeomeanOracle} from "@bananapus/buyback-hook-v6/src/interfaces/IGeomeanOracle.sol";
46
58
 
@@ -49,10 +61,12 @@ import {IPoolManager} from "@uniswap/v4-core/src/interfaces/IPoolManager.sol";
49
61
  import {IUnlockCallback} from "@uniswap/v4-core/src/interfaces/callback/IUnlockCallback.sol";
50
62
  import {IHooks} from "@uniswap/v4-core/src/interfaces/IHooks.sol";
51
63
  import {PoolKey} from "@uniswap/v4-core/src/types/PoolKey.sol";
64
+ // forge-lint: disable-next-line(unused-import)
52
65
  import {PoolId, PoolIdLibrary} from "@uniswap/v4-core/src/types/PoolId.sol";
53
66
  import {Currency, CurrencyLibrary} from "@uniswap/v4-core/src/types/Currency.sol";
54
67
  import {BalanceDelta} from "@uniswap/v4-core/src/types/BalanceDelta.sol";
55
68
  import {ModifyLiquidityParams, SwapParams} from "@uniswap/v4-core/src/types/PoolOperation.sol";
69
+ // forge-lint: disable-next-line(unused-import)
56
70
  import {TickMath} from "@uniswap/v4-core/src/libraries/TickMath.sol";
57
71
  import {StateLibrary} from "@uniswap/v4-core/src/libraries/StateLibrary.sol";
58
72
 
@@ -60,6 +74,7 @@ import {IERC20} from "@openzeppelin/contracts/interfaces/IERC20.sol";
60
74
 
61
75
  /// @notice Helper that adds liquidity to a V4 pool via the unlock/callback pattern.
62
76
  contract LiquidityHelper is IUnlockCallback {
77
+ // forge-lint: disable-next-line(screaming-snake-case-immutable)
63
78
  IPoolManager public immutable poolManager;
64
79
 
65
80
  enum Action {
@@ -95,7 +110,8 @@ contract LiquidityHelper is IUnlockCallback {
95
110
  payable
96
111
  {
97
112
  bytes memory data =
98
- abi.encode(Action.ADD_LIQUIDITY, abi.encode(AddLiqParams(key, tickLower, tickUpper, liquidityDelta)));
113
+ // forge-lint: disable-next-line(named-struct-fields)
114
+ abi.encode(Action.ADD_LIQUIDITY, abi.encode(AddLiqParams(key, tickLower, tickUpper, liquidityDelta)));
99
115
  poolManager.unlock(data);
100
116
  }
101
117
 
@@ -109,7 +125,8 @@ contract LiquidityHelper is IUnlockCallback {
109
125
  payable
110
126
  {
111
127
  bytes memory data =
112
- abi.encode(Action.SWAP, abi.encode(DoSwapParams(key, zeroForOne, amountSpecified, sqrtPriceLimitX96)));
128
+ // forge-lint: disable-next-line(named-struct-fields)
129
+ abi.encode(Action.SWAP, abi.encode(DoSwapParams(key, zeroForOne, amountSpecified, sqrtPriceLimitX96)));
113
130
  poolManager.unlock(data);
114
131
  }
115
132
 
@@ -151,7 +168,10 @@ contract LiquidityHelper is IUnlockCallback {
151
168
  DoSwapParams memory params = abi.decode(data, (DoSwapParams));
152
169
 
153
170
  BalanceDelta delta = poolManager.swap(
154
- params.key, SwapParams(params.zeroForOne, params.amountSpecified, params.sqrtPriceLimitX96), ""
171
+ params.key,
172
+ // forge-lint: disable-next-line(named-struct-fields)
173
+ SwapParams(params.zeroForOne, params.amountSpecified, params.sqrtPriceLimitX96),
174
+ ""
155
175
  );
156
176
 
157
177
  if (delta.amount0() < 0) {
@@ -170,12 +190,14 @@ contract LiquidityHelper is IUnlockCallback {
170
190
 
171
191
  function _settleIfNegative(Currency currency, int128 delta) internal {
172
192
  if (delta >= 0) return;
193
+ // forge-lint: disable-next-line(unsafe-typecast)
173
194
  uint256 amount = uint256(uint128(-delta));
174
195
 
175
196
  if (currency.isAddressZero()) {
176
197
  poolManager.settle{value: amount}();
177
198
  } else {
178
199
  poolManager.sync(currency);
200
+ // forge-lint: disable-next-line(erc20-unchecked-transfer)
179
201
  IERC20(Currency.unwrap(currency)).transfer(address(poolManager), amount);
180
202
  poolManager.settle();
181
203
  }
@@ -183,6 +205,7 @@ contract LiquidityHelper is IUnlockCallback {
183
205
 
184
206
  function _takeIfPositive(Currency currency, int128 delta) internal {
185
207
  if (delta <= 0) return;
208
+ // forge-lint: disable-next-line(unsafe-typecast)
186
209
  uint256 amount = uint256(uint128(delta));
187
210
  poolManager.take(currency, address(this), amount);
188
211
  }
@@ -211,24 +234,38 @@ abstract contract ForkTestBase is TestBaseWorkflow {
211
234
  // ───────────────────────── State
212
235
  // ─────────────────────────
213
236
 
237
+ // forge-lint: disable-next-line(mixed-case-variable)
214
238
  REVDeployer REV_DEPLOYER;
239
+ // forge-lint: disable-next-line(mixed-case-variable)
215
240
  JBBuybackHook BUYBACK_HOOK;
241
+ // forge-lint: disable-next-line(mixed-case-variable)
216
242
  JBBuybackHookRegistry BUYBACK_REGISTRY;
243
+ // forge-lint: disable-next-line(mixed-case-variable)
217
244
  JB721TiersHook EXAMPLE_HOOK;
245
+ // forge-lint: disable-next-line(mixed-case-variable)
218
246
  IJB721TiersHookDeployer HOOK_DEPLOYER;
247
+ // forge-lint: disable-next-line(mixed-case-variable)
219
248
  IJB721TiersHookStore HOOK_STORE;
249
+ // forge-lint: disable-next-line(mixed-case-variable)
220
250
  IJBAddressRegistry ADDRESS_REGISTRY;
251
+ // forge-lint: disable-next-line(mixed-case-variable)
221
252
  IREVLoans LOANS_CONTRACT;
253
+ // forge-lint: disable-next-line(mixed-case-variable)
222
254
  IJBSuckerRegistry SUCKER_REGISTRY;
255
+ // forge-lint: disable-next-line(mixed-case-variable)
223
256
  CTPublisher PUBLISHER;
224
257
  IPoolManager poolManager;
225
258
  LiquidityHelper liqHelper;
226
259
 
260
+ // forge-lint: disable-next-line(mixed-case-variable)
227
261
  uint256 FEE_PROJECT_ID;
228
262
 
229
263
  address private constant TRUSTED_FORWARDER = 0xB2b5841DBeF766d4b521221732F9B618fCf34A87;
264
+ // forge-lint: disable-next-line(mixed-case-variable)
230
265
  address PAYER = makeAddr("payer");
266
+ // forge-lint: disable-next-line(mixed-case-variable)
231
267
  address BORROWER = makeAddr("borrower");
268
+ // forge-lint: disable-next-line(mixed-case-variable)
232
269
  address SPLIT_BENEFICIARY = makeAddr("splitBeneficiary");
233
270
 
234
271
  // Tier configuration: 1 ETH tier with 30% split.
@@ -256,8 +293,9 @@ abstract contract ForkTestBase is TestBaseWorkflow {
256
293
 
257
294
  SUCKER_REGISTRY = new JBSuckerRegistry(jbDirectory(), jbPermissions(), multisig(), address(0));
258
295
  HOOK_STORE = new JB721TiersHookStore();
259
- EXAMPLE_HOOK =
260
- new JB721TiersHook(jbDirectory(), jbPermissions(), jbRulesets(), HOOK_STORE, jbSplits(), multisig());
296
+ EXAMPLE_HOOK = new JB721TiersHook(
297
+ jbDirectory(), jbPermissions(), jbPrices(), jbRulesets(), HOOK_STORE, jbSplits(), multisig()
298
+ );
261
299
  ADDRESS_REGISTRY = new JBAddressRegistry();
262
300
  HOOK_DEPLOYER = new JB721TiersHookDeployer(EXAMPLE_HOOK, HOOK_STORE, ADDRESS_REGISTRY, multisig());
263
301
  PUBLISHER = new CTPublisher(jbDirectory(), jbPermissions(), FEE_PROJECT_ID, multisig());
@@ -343,6 +381,7 @@ abstract contract ForkTestBase is TestBaseWorkflow {
343
381
  });
344
382
 
345
383
  cfg = REVConfig({
384
+ // forge-lint: disable-next-line(named-struct-fields)
346
385
  description: REVDescription("Fork Test", "FORK", "ipfs://fork", "FORK_SALT"),
347
386
  baseCurrency: uint32(uint160(JBConstants.NATIVE_TOKEN)),
348
387
  splitOperator: multisig(),
@@ -372,6 +411,7 @@ abstract contract ForkTestBase is TestBaseWorkflow {
372
411
  votingUnits: 0,
373
412
  reserveFrequency: 0,
374
413
  reserveBeneficiary: address(0),
414
+ // forge-lint: disable-next-line(unsafe-typecast)
375
415
  encodedIPFSUri: bytes32("tier1"),
376
416
  category: 1,
377
417
  discountPercent: 0,
@@ -393,10 +433,7 @@ abstract contract ForkTestBase is TestBaseWorkflow {
393
433
  tokenUriResolver: IJB721TokenUriResolver(address(0)),
394
434
  contractUri: "ipfs://contract",
395
435
  tiersConfig: JB721InitTiersConfig({
396
- tiers: tiers,
397
- currency: uint32(uint160(JBConstants.NATIVE_TOKEN)),
398
- decimals: 18,
399
- prices: IJBPrices(address(0))
436
+ tiers: tiers, currency: uint32(uint160(JBConstants.NATIVE_TOKEN)), decimals: 18
400
437
  }),
401
438
  reserveBeneficiary: address(0),
402
439
  flags: REV721TiersHookFlags({
@@ -406,11 +443,12 @@ abstract contract ForkTestBase is TestBaseWorkflow {
406
443
  preventOverspending: false
407
444
  })
408
445
  }),
446
+ // forge-lint: disable-next-line(unsafe-typecast)
409
447
  salt: bytes32("FORK_721"),
410
- splitOperatorCanAdjustTiers: false,
411
- splitOperatorCanUpdateMetadata: false,
412
- splitOperatorCanMint: false,
413
- splitOperatorCanIncreaseDiscountPercent: false
448
+ preventSplitOperatorAdjustingTiers: false,
449
+ preventSplitOperatorUpdatingMetadata: false,
450
+ preventSplitOperatorMinting: false,
451
+ preventSplitOperatorIncreasingDiscountPercent: false
414
452
  });
415
453
  }
416
454
 
@@ -421,6 +459,7 @@ abstract contract ForkTestBase is TestBaseWorkflow {
421
459
  function _deployFeeProject(uint16 cashOutTaxRate) internal {
422
460
  (REVConfig memory feeCfg, JBTerminalConfig[] memory feeTc, REVSuckerDeploymentConfig memory feeSdc) =
423
461
  _buildMinimalConfig(cashOutTaxRate);
462
+ // forge-lint: disable-next-line(named-struct-fields)
424
463
  feeCfg.description = REVDescription("Fee", "FEE", "ipfs://fee", "FEE_SALT");
425
464
 
426
465
  vm.prank(multisig());
@@ -428,7 +467,9 @@ abstract contract ForkTestBase is TestBaseWorkflow {
428
467
  revnetId: FEE_PROJECT_ID,
429
468
  configuration: feeCfg,
430
469
  terminalConfigurations: feeTc,
431
- suckerDeploymentConfiguration: feeSdc
470
+ suckerDeploymentConfiguration: feeSdc,
471
+ tiered721HookConfiguration: REVEmpty721Config.empty721Config(uint32(uint160(JBConstants.NATIVE_TOKEN))),
472
+ allowedPosts: REVEmpty721Config.emptyAllowedPosts()
432
473
  });
433
474
  }
434
475
 
@@ -437,8 +478,13 @@ abstract contract ForkTestBase is TestBaseWorkflow {
437
478
  (REVConfig memory cfg, JBTerminalConfig[] memory tc, REVSuckerDeploymentConfig memory sdc) =
438
479
  _buildMinimalConfig(cashOutTaxRate);
439
480
 
440
- revnetId = REV_DEPLOYER.deployFor({
441
- revnetId: 0, configuration: cfg, terminalConfigurations: tc, suckerDeploymentConfiguration: sdc
481
+ (revnetId,) = REV_DEPLOYER.deployFor({
482
+ revnetId: 0,
483
+ configuration: cfg,
484
+ terminalConfigurations: tc,
485
+ suckerDeploymentConfiguration: sdc,
486
+ tiered721HookConfiguration: REVEmpty721Config.empty721Config(uint32(uint160(JBConstants.NATIVE_TOKEN))),
487
+ allowedPosts: REVEmpty721Config.emptyAllowedPosts()
442
488
  });
443
489
  }
444
490
 
@@ -450,7 +496,7 @@ abstract contract ForkTestBase is TestBaseWorkflow {
450
496
  cfg.description.salt = "FORK_721_SALT";
451
497
  REVDeploy721TiersHookConfig memory hookConfig = _build721Config();
452
498
 
453
- (revnetId, hook) = REV_DEPLOYER.deployWith721sFor({
499
+ (revnetId, hook) = REV_DEPLOYER.deployFor({
454
500
  revnetId: 0,
455
501
  configuration: cfg,
456
502
  terminalConfigurations: tc,
@@ -494,6 +540,7 @@ abstract contract ForkTestBase is TestBaseWorkflow {
494
540
  IERC20(projectToken).approve(address(poolManager), type(uint256).max);
495
541
  vm.stopPrank();
496
542
 
543
+ // forge-lint: disable-next-line(unsafe-typecast)
497
544
  int256 liquidityDelta = int256(liquidityTokenAmount / 2);
498
545
  vm.prank(address(liqHelper));
499
546
  liqHelper.addLiquidity{value: liquidityTokenAmount}(key, TICK_LOWER, TICK_UPPER, liquidityDelta);
@@ -507,12 +554,14 @@ abstract contract ForkTestBase is TestBaseWorkflow {
507
554
 
508
555
  int56[] memory tickCumulatives = new int56[](2);
509
556
  tickCumulatives[0] = 0;
557
+ // forge-lint: disable-next-line(unsafe-typecast)
510
558
  tickCumulatives[1] = int56(tick) * int56(int32(twapWindow));
511
559
 
512
560
  uint136[] memory secondsPerLiquidityCumulativeX128s = new uint136[](2);
513
561
  secondsPerLiquidityCumulativeX128s[0] = 0;
514
562
  uint256 liq = uint256(liquidity > 0 ? liquidity : -liquidity);
515
563
  if (liq == 0) liq = 1;
564
+ // forge-lint: disable-next-line(unsafe-typecast)
516
565
  secondsPerLiquidityCumulativeX128s[1] = uint136((uint256(twapWindow) << 128) / liq);
517
566
 
518
567
  vm.mockCall(