@rev-net/core-v6 0.0.6 → 0.0.8
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/SKILLS.md +1 -1
- package/docs/book.toml +1 -1
- package/docs/src/README.md +151 -54
- package/docs/src/SUMMARY.md +0 -2
- package/docs/src/src/REVDeployer.sol/contract.REVDeployer.md +148 -117
- package/docs/src/src/REVLoans.sol/contract.REVLoans.md +120 -59
- package/docs/src/src/interfaces/IREVDeployer.sol/interface.IREVDeployer.md +296 -14
- package/docs/src/src/interfaces/IREVLoans.sol/interface.IREVLoans.md +318 -16
- package/docs/src/src/structs/README.md +0 -2
- package/docs/src/src/structs/REVAutoIssuance.sol/struct.REVAutoIssuance.md +4 -4
- package/docs/src/src/structs/REVConfig.sol/struct.REVConfig.md +5 -17
- package/docs/src/src/structs/REVCroptopAllowedPost.sol/struct.REVCroptopAllowedPost.md +10 -6
- package/docs/src/src/structs/REVDeploy721TiersHookConfig.sol/struct.REVDeploy721TiersHookConfig.md +7 -7
- package/docs/src/src/structs/REVDescription.sol/struct.REVDescription.md +5 -5
- package/docs/src/src/structs/REVLoan.sol/struct.REVLoan.md +7 -7
- package/docs/src/src/structs/REVLoanSource.sol/struct.REVLoanSource.md +3 -3
- package/docs/src/src/structs/REVStageConfig.sol/struct.REVStageConfig.md +10 -10
- package/docs/src/src/structs/REVSuckerDeploymentConfig.sol/struct.REVSuckerDeploymentConfig.md +3 -3
- package/foundry.toml +1 -1
- package/package.json +11 -8
- package/slither-ci.config.json +1 -1
- package/src/REVDeployer.sol +102 -68
- package/src/REVLoans.sol +180 -169
- package/src/interfaces/IREVDeployer.sol +109 -73
- package/src/interfaces/IREVLoans.sol +119 -73
- package/test/TestPR27_CEIPattern.t.sol +2 -2
- package/test/TestPR32_MixedFixes.t.sol +1 -1
- package/test/mock/MockBuybackDataHook.sol +8 -4
- package/test/mock/MockBuybackDataHookMintPath.sol +7 -3
- package/test/regression/TestI20_CumulativeLoanCounter.t.sol +303 -0
- package/test/regression/TestL27_LiquidateGapHandling.t.sol +334 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
# REVLoan
|
|
2
|
-
[Git Source](https://github.com/rev-net/revnet-core-
|
|
2
|
+
[Git Source](https://github.com/rev-net/revnet-core-v6/blob/94c003a3a16de2bd012d63cccedd6bd38d21f6e7/src/structs/REVLoan.sol)
|
|
3
3
|
|
|
4
4
|
**Notes:**
|
|
5
5
|
- member: borrowedAmount The amount that is being borrowed.
|
|
@@ -17,12 +17,12 @@
|
|
|
17
17
|
|
|
18
18
|
```solidity
|
|
19
19
|
struct REVLoan {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
20
|
+
uint112 amount;
|
|
21
|
+
uint112 collateral;
|
|
22
|
+
uint48 createdAt;
|
|
23
|
+
uint16 prepaidFeePercent;
|
|
24
|
+
uint32 prepaidDuration;
|
|
25
|
+
REVLoanSource source;
|
|
26
26
|
}
|
|
27
27
|
```
|
|
28
28
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
# REVLoanSource
|
|
2
|
-
[Git Source](https://github.com/rev-net/revnet-core-
|
|
2
|
+
[Git Source](https://github.com/rev-net/revnet-core-v6/blob/94c003a3a16de2bd012d63cccedd6bd38d21f6e7/src/structs/REVLoanSource.sol)
|
|
3
3
|
|
|
4
4
|
**Notes:**
|
|
5
5
|
- member: token The token that is being loaned.
|
|
@@ -9,8 +9,8 @@
|
|
|
9
9
|
|
|
10
10
|
```solidity
|
|
11
11
|
struct REVLoanSource {
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
address token;
|
|
13
|
+
IJBPayoutTerminal terminal;
|
|
14
14
|
}
|
|
15
15
|
```
|
|
16
16
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
# REVStageConfig
|
|
2
|
-
[Git Source](https://github.com/rev-net/revnet-core-
|
|
2
|
+
[Git Source](https://github.com/rev-net/revnet-core-v6/blob/94c003a3a16de2bd012d63cccedd6bd38d21f6e7/src/structs/REVStageConfig.sol)
|
|
3
3
|
|
|
4
4
|
**Notes:**
|
|
5
5
|
- member: startsAtOrAfter The timestamp to start a stage at the given rate at or after.
|
|
@@ -30,15 +30,15 @@ out.
|
|
|
30
30
|
|
|
31
31
|
```solidity
|
|
32
32
|
struct REVStageConfig {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
33
|
+
uint48 startsAtOrAfter;
|
|
34
|
+
REVAutoIssuance[] autoIssuances;
|
|
35
|
+
uint16 splitPercent;
|
|
36
|
+
JBSplit[] splits;
|
|
37
|
+
uint112 initialIssuance;
|
|
38
|
+
uint32 issuanceCutFrequency;
|
|
39
|
+
uint32 issuanceCutPercent;
|
|
40
|
+
uint16 cashOutTaxRate;
|
|
41
|
+
uint16 extraMetadata;
|
|
42
42
|
}
|
|
43
43
|
```
|
|
44
44
|
|
package/docs/src/src/structs/REVSuckerDeploymentConfig.sol/struct.REVSuckerDeploymentConfig.md
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
# REVSuckerDeploymentConfig
|
|
2
|
-
[Git Source](https://github.com/rev-net/revnet-core-
|
|
2
|
+
[Git Source](https://github.com/rev-net/revnet-core-v6/blob/94c003a3a16de2bd012d63cccedd6bd38d21f6e7/src/structs/REVSuckerDeploymentConfig.sol)
|
|
3
3
|
|
|
4
4
|
**Notes:**
|
|
5
5
|
- member: deployerConfigurations The information for how to suck tokens to other chains.
|
|
@@ -9,8 +9,8 @@
|
|
|
9
9
|
|
|
10
10
|
```solidity
|
|
11
11
|
struct REVSuckerDeploymentConfig {
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
JBSuckerDeployerConfig[] deployerConfigurations;
|
|
13
|
+
bytes32 salt;
|
|
14
14
|
}
|
|
15
15
|
```
|
|
16
16
|
|
package/foundry.toml
CHANGED
package/package.json
CHANGED
|
@@ -1,15 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rev-net/core-v6",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.8",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
7
7
|
"url": "git+https://github.com/rev-net/revnet-core-v6"
|
|
8
8
|
},
|
|
9
|
+
"engines": {
|
|
10
|
+
"node": ">=20.0.0"
|
|
11
|
+
},
|
|
9
12
|
"scripts": {
|
|
10
13
|
"postinstall": "find node_modules -name '*.sol' -type f | xargs grep -l 'pragma solidity 0.8.23;' 2>/dev/null | xargs sed -i '' 's/pragma solidity 0.8.23;/pragma solidity 0.8.26;/g' 2>/dev/null || true",
|
|
11
14
|
"test": "forge test",
|
|
12
|
-
"coverage
|
|
15
|
+
"coverage": "forge coverage --match-path \"./src/*.sol\" --report lcov --report summary",
|
|
13
16
|
"deploy:mainnets": "source ./.env && export START_TIME=$(date +%s) && npx sphinx propose ./script/Deploy.s.sol --networks mainnets",
|
|
14
17
|
"deploy:mainnets:1_1": "source ./.env && npx sphinx propose ./script/Deploy1_1.s.sol --networks mainnets",
|
|
15
18
|
"deploy:testnets": "source ./.env && export START_TIME=$(date +%s) && npx sphinx propose ./script/Deploy.s.sol --networks testnets",
|
|
@@ -17,16 +20,16 @@
|
|
|
17
20
|
"artifacts": "source ./.env && npx sphinx artifacts --org-id 'ea165b21-7cdc-4d7b-be59-ecdd4c26bee4' --project-name 'revnet-core-v6'"
|
|
18
21
|
},
|
|
19
22
|
"dependencies": {
|
|
20
|
-
"@bananapus/721-hook-v6": "^0.0.
|
|
21
|
-
"@bananapus/buyback-hook-v6": "^0.0.
|
|
22
|
-
"@bananapus/core-v6": "^0.0.
|
|
23
|
-
"@bananapus/permission-ids-v6": "^0.0.
|
|
24
|
-
"@bananapus/suckers-v6": "^0.0.
|
|
23
|
+
"@bananapus/721-hook-v6": "^0.0.9",
|
|
24
|
+
"@bananapus/buyback-hook-v6": "^0.0.7",
|
|
25
|
+
"@bananapus/core-v6": "^0.0.10",
|
|
26
|
+
"@bananapus/permission-ids-v6": "^0.0.5",
|
|
27
|
+
"@bananapus/suckers-v6": "^0.0.7",
|
|
25
28
|
"@bananapus/router-terminal-v6": "^0.0.6",
|
|
26
29
|
"@croptop/core-v6": "^0.0.6",
|
|
27
30
|
"@openzeppelin/contracts": "^5.2.0"
|
|
28
31
|
},
|
|
29
32
|
"devDependencies": {
|
|
30
|
-
"@sphinx-labs/plugins": "^0.33.
|
|
33
|
+
"@sphinx-labs/plugins": "^0.33.2"
|
|
31
34
|
}
|
|
32
35
|
}
|
package/slither-ci.config.json
CHANGED
package/src/REVDeployer.sol
CHANGED
|
@@ -1,15 +1,18 @@
|
|
|
1
1
|
// SPDX-License-Identifier: MIT
|
|
2
2
|
pragma solidity 0.8.26;
|
|
3
3
|
|
|
4
|
+
import {ERC2771Context} from "@openzeppelin/contracts/metatx/ERC2771Context.sol";
|
|
4
5
|
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
|
|
6
|
+
import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
|
|
5
7
|
import {IERC721} from "@openzeppelin/contracts/token/ERC721/IERC721.sol";
|
|
6
8
|
import {IERC721Receiver} from "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol";
|
|
7
|
-
import {ERC2771Context} from "@openzeppelin/contracts/metatx/ERC2771Context.sol";
|
|
8
|
-
import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
|
|
9
9
|
import {mulDiv} from "@prb/math/src/Common.sol";
|
|
10
10
|
import {IJB721TiersHook} from "@bananapus/721-hook-v6/src/interfaces/IJB721TiersHook.sol";
|
|
11
11
|
import {IJB721TiersHookDeployer} from "@bananapus/721-hook-v6/src/interfaces/IJB721TiersHookDeployer.sol";
|
|
12
12
|
import {IJBBuybackHook} from "@bananapus/buyback-hook-v6/src/interfaces/IJBBuybackHook.sol";
|
|
13
|
+
import {Currency} from "@uniswap/v4-core/src/types/Currency.sol";
|
|
14
|
+
import {IHooks} from "@uniswap/v4-core/src/interfaces/IHooks.sol";
|
|
15
|
+
import {PoolKey} from "@uniswap/v4-core/src/types/PoolKey.sol";
|
|
13
16
|
import {IJBCashOutHook} from "@bananapus/core-v6/src/interfaces/IJBCashOutHook.sol";
|
|
14
17
|
import {IJBController} from "@bananapus/core-v6/src/interfaces/IJBController.sol";
|
|
15
18
|
import {IJBDirectory} from "@bananapus/core-v6/src/interfaces/IJBDirectory.sol";
|
|
@@ -26,19 +29,19 @@ import {JBConstants} from "@bananapus/core-v6/src/libraries/JBConstants.sol";
|
|
|
26
29
|
import {JBSplitGroupIds} from "@bananapus/core-v6/src/libraries/JBSplitGroupIds.sol";
|
|
27
30
|
import {JBAccountingContext} from "@bananapus/core-v6/src/structs/JBAccountingContext.sol";
|
|
28
31
|
import {JBAfterCashOutRecordedContext} from "@bananapus/core-v6/src/structs/JBAfterCashOutRecordedContext.sol";
|
|
29
|
-
import {JBBeforePayRecordedContext} from "@bananapus/core-v6/src/structs/JBBeforePayRecordedContext.sol";
|
|
30
32
|
import {JBBeforeCashOutRecordedContext} from "@bananapus/core-v6/src/structs/JBBeforeCashOutRecordedContext.sol";
|
|
33
|
+
import {JBBeforePayRecordedContext} from "@bananapus/core-v6/src/structs/JBBeforePayRecordedContext.sol";
|
|
34
|
+
import {JBCashOutHookSpecification} from "@bananapus/core-v6/src/structs/JBCashOutHookSpecification.sol";
|
|
31
35
|
import {JBCurrencyAmount} from "@bananapus/core-v6/src/structs/JBCurrencyAmount.sol";
|
|
32
36
|
import {JBFundAccessLimitGroup} from "@bananapus/core-v6/src/structs/JBFundAccessLimitGroup.sol";
|
|
33
|
-
import {JBPermissionsData} from "@bananapus/core-v6/src/structs/JBPermissionsData.sol";
|
|
34
37
|
import {JBPayHookSpecification} from "@bananapus/core-v6/src/structs/JBPayHookSpecification.sol";
|
|
38
|
+
import {JBPermissionsData} from "@bananapus/core-v6/src/structs/JBPermissionsData.sol";
|
|
35
39
|
import {JBRuleset} from "@bananapus/core-v6/src/structs/JBRuleset.sol";
|
|
36
40
|
import {JBRulesetConfig} from "@bananapus/core-v6/src/structs/JBRulesetConfig.sol";
|
|
37
41
|
import {JBRulesetMetadata} from "@bananapus/core-v6/src/structs/JBRulesetMetadata.sol";
|
|
38
42
|
import {JBSplit} from "@bananapus/core-v6/src/structs/JBSplit.sol";
|
|
39
43
|
import {JBSplitGroup} from "@bananapus/core-v6/src/structs/JBSplitGroup.sol";
|
|
40
44
|
import {JBTerminalConfig} from "@bananapus/core-v6/src/structs/JBTerminalConfig.sol";
|
|
41
|
-
import {JBCashOutHookSpecification} from "@bananapus/core-v6/src/structs/JBCashOutHookSpecification.sol";
|
|
42
45
|
import {JBPermissionIds} from "@bananapus/permission-ids-v6/src/JBPermissionIds.sol";
|
|
43
46
|
import {IJBSuckerRegistry} from "@bananapus/suckers-v6/src/interfaces/IJBSuckerRegistry.sol";
|
|
44
47
|
import {CTPublisher} from "@croptop/core-v6/src/CTPublisher.sol";
|
|
@@ -67,11 +70,11 @@ contract REVDeployer is ERC2771Context, IREVDeployer, IJBRulesetDataHook, IJBCas
|
|
|
67
70
|
error REVDeployer_CashOutsCantBeTurnedOffCompletely(uint256 cashOutTaxRate, uint256 maxCashOutTaxRate);
|
|
68
71
|
error REVDeployer_MustHaveSplits();
|
|
69
72
|
error REVDeployer_NothingToAutoIssue();
|
|
73
|
+
error REVDeployer_NothingToBurn();
|
|
70
74
|
error REVDeployer_RulesetDoesNotAllowDeployingSuckers();
|
|
71
75
|
error REVDeployer_StageNotStarted(uint256 stageId);
|
|
72
76
|
error REVDeployer_StagesRequired();
|
|
73
77
|
error REVDeployer_StageTimesMustIncrease();
|
|
74
|
-
error REVDeployer_NothingToBurn();
|
|
75
78
|
error REVDeployer_Unauthorized(uint256 revnetId, address caller);
|
|
76
79
|
|
|
77
80
|
//*********************************************************************//
|
|
@@ -95,6 +98,10 @@ contract REVDeployer is ERC2771Context, IREVDeployer, IJBRulesetDataHook, IJBCas
|
|
|
95
98
|
/// @dev 10_000 = 1%. This is the standard fee tier for most project token pairs.
|
|
96
99
|
uint24 public constant DEFAULT_BUYBACK_POOL_FEE = 10_000;
|
|
97
100
|
|
|
101
|
+
/// @notice The default tick spacing used when auto-configuring buyback pools.
|
|
102
|
+
/// @dev 60 is the standard tick spacing for the 1% fee tier.
|
|
103
|
+
int24 public constant DEFAULT_BUYBACK_TICK_SPACING = 60;
|
|
104
|
+
|
|
98
105
|
/// @notice The default TWAP window used when auto-configuring buyback pools.
|
|
99
106
|
/// @dev 2 days provides robust manipulation resistance.
|
|
100
107
|
uint32 public constant DEFAULT_BUYBACK_TWAP_WINDOW = 2 days;
|
|
@@ -224,49 +231,6 @@ contract REVDeployer is ERC2771Context, IREVDeployer, IJBRulesetDataHook, IJBCas
|
|
|
224
231
|
// ------------------------- external views -------------------------- //
|
|
225
232
|
//*********************************************************************//
|
|
226
233
|
|
|
227
|
-
/// @notice Before a revnet processes an incoming payment, determine the weight and pay hooks to use.
|
|
228
|
-
/// @dev This function is part of `IJBRulesetDataHook`, and gets called before the revnet processes a payment.
|
|
229
|
-
/// @param context Standard Juicebox payment context. See `JBBeforePayRecordedContext`.
|
|
230
|
-
/// @return weight The weight which revnet tokens are minted relative to. This can be used to customize how many
|
|
231
|
-
/// tokens get minted by a payment.
|
|
232
|
-
/// @return hookSpecifications Amounts (out of what's being paid in) to be sent to pay hooks instead of being paid
|
|
233
|
-
/// into the revnet. Useful for automatically routing funds from a treasury as payments come in.
|
|
234
|
-
function beforePayRecordedWith(JBBeforePayRecordedContext calldata context)
|
|
235
|
-
external
|
|
236
|
-
view
|
|
237
|
-
override
|
|
238
|
-
returns (uint256 weight, JBPayHookSpecification[] memory hookSpecifications)
|
|
239
|
-
{
|
|
240
|
-
// Keep a reference to the specifications provided by the buyback hook.
|
|
241
|
-
JBPayHookSpecification[] memory buybackHookSpecifications;
|
|
242
|
-
|
|
243
|
-
// Read the weight and specifications from the buyback hook.
|
|
244
|
-
(weight, buybackHookSpecifications) = BUYBACK_HOOK.beforePayRecordedWith(context);
|
|
245
|
-
|
|
246
|
-
// Keep a reference to the revnet's tiered ERC-721 hook.
|
|
247
|
-
IJB721TiersHook tiered721Hook = tiered721HookOf[context.projectId];
|
|
248
|
-
|
|
249
|
-
// Is there a tiered ERC-721 hook?
|
|
250
|
-
bool usesTiered721Hook = address(tiered721Hook) != address(0);
|
|
251
|
-
|
|
252
|
-
// Did the buyback hook return any specifications? (It won't when direct minting is cheaper than swapping.)
|
|
253
|
-
bool usesBuybackHook = buybackHookSpecifications.length > 0;
|
|
254
|
-
|
|
255
|
-
// Initialize the returned specification array with only the hooks that are present.
|
|
256
|
-
hookSpecifications = new JBPayHookSpecification[]((usesTiered721Hook ? 1 : 0) + (usesBuybackHook ? 1 : 0));
|
|
257
|
-
|
|
258
|
-
// If we have a tiered ERC-721 hook, add it to the array.
|
|
259
|
-
if (usesTiered721Hook) {
|
|
260
|
-
hookSpecifications[0] =
|
|
261
|
-
JBPayHookSpecification({hook: IJBPayHook(address(tiered721Hook)), amount: 0, metadata: bytes("")});
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
// Add the buyback hook specification if present.
|
|
265
|
-
if (usesBuybackHook) {
|
|
266
|
-
hookSpecifications[usesTiered721Hook ? 1 : 0] = buybackHookSpecifications[0];
|
|
267
|
-
}
|
|
268
|
-
}
|
|
269
|
-
|
|
270
234
|
/// @notice Determine how a cash out from a revnet should be processed.
|
|
271
235
|
/// @dev This function is part of `IJBRulesetDataHook`, and gets called before the revnet processes a cash out.
|
|
272
236
|
/// @dev If a sucker is cashing out, no taxes or fees are imposed.
|
|
@@ -339,6 +303,49 @@ contract REVDeployer is ERC2771Context, IREVDeployer, IJBRulesetDataHook, IJBCas
|
|
|
339
303
|
return (context.cashOutTaxRate, nonFeeCashOutCount, context.totalSupply, hookSpecifications);
|
|
340
304
|
}
|
|
341
305
|
|
|
306
|
+
/// @notice Before a revnet processes an incoming payment, determine the weight and pay hooks to use.
|
|
307
|
+
/// @dev This function is part of `IJBRulesetDataHook`, and gets called before the revnet processes a payment.
|
|
308
|
+
/// @param context Standard Juicebox payment context. See `JBBeforePayRecordedContext`.
|
|
309
|
+
/// @return weight The weight which revnet tokens are minted relative to. This can be used to customize how many
|
|
310
|
+
/// tokens get minted by a payment.
|
|
311
|
+
/// @return hookSpecifications Amounts (out of what's being paid in) to be sent to pay hooks instead of being paid
|
|
312
|
+
/// into the revnet. Useful for automatically routing funds from a treasury as payments come in.
|
|
313
|
+
function beforePayRecordedWith(JBBeforePayRecordedContext calldata context)
|
|
314
|
+
external
|
|
315
|
+
view
|
|
316
|
+
override
|
|
317
|
+
returns (uint256 weight, JBPayHookSpecification[] memory hookSpecifications)
|
|
318
|
+
{
|
|
319
|
+
// Keep a reference to the specifications provided by the buyback hook.
|
|
320
|
+
JBPayHookSpecification[] memory buybackHookSpecifications;
|
|
321
|
+
|
|
322
|
+
// Read the weight and specifications from the buyback hook.
|
|
323
|
+
(weight, buybackHookSpecifications) = BUYBACK_HOOK.beforePayRecordedWith(context);
|
|
324
|
+
|
|
325
|
+
// Keep a reference to the revnet's tiered ERC-721 hook.
|
|
326
|
+
IJB721TiersHook tiered721Hook = tiered721HookOf[context.projectId];
|
|
327
|
+
|
|
328
|
+
// Is there a tiered ERC-721 hook?
|
|
329
|
+
bool usesTiered721Hook = address(tiered721Hook) != address(0);
|
|
330
|
+
|
|
331
|
+
// Did the buyback hook return any specifications? (It won't when direct minting is cheaper than swapping.)
|
|
332
|
+
bool usesBuybackHook = buybackHookSpecifications.length > 0;
|
|
333
|
+
|
|
334
|
+
// Initialize the returned specification array with only the hooks that are present.
|
|
335
|
+
hookSpecifications = new JBPayHookSpecification[]((usesTiered721Hook ? 1 : 0) + (usesBuybackHook ? 1 : 0));
|
|
336
|
+
|
|
337
|
+
// If we have a tiered ERC-721 hook, add it to the array.
|
|
338
|
+
if (usesTiered721Hook) {
|
|
339
|
+
hookSpecifications[0] =
|
|
340
|
+
JBPayHookSpecification({hook: IJBPayHook(address(tiered721Hook)), amount: 0, metadata: bytes("")});
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
// Add the buyback hook specification if present.
|
|
344
|
+
if (usesBuybackHook) {
|
|
345
|
+
hookSpecifications[usesTiered721Hook ? 1 : 0] = buybackHookSpecifications[0];
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
|
|
342
349
|
/// @notice A flag indicating whether an address has permission to mint a revnet's tokens on-demand.
|
|
343
350
|
/// @dev Required by the `IJBRulesetDataHook` interface.
|
|
344
351
|
/// @param revnetId The ID of the revnet to check permissions for.
|
|
@@ -459,18 +466,45 @@ contract REVDeployer is ERC2771Context, IREVDeployer, IJBRulesetDataHook, IJBCas
|
|
|
459
466
|
});
|
|
460
467
|
|
|
461
468
|
// Configure a buyback pool for this terminal token with default fee and TWAP window.
|
|
462
|
-
// slither-disable-next-line
|
|
463
|
-
|
|
464
|
-
.setPoolFor({
|
|
465
|
-
projectId: revnetId,
|
|
466
|
-
fee: DEFAULT_BUYBACK_POOL_FEE,
|
|
467
|
-
twapWindow: DEFAULT_BUYBACK_TWAP_WINDOW,
|
|
468
|
-
terminalToken: accountingContext.token
|
|
469
|
-
});
|
|
469
|
+
// slither-disable-next-line calls-loop
|
|
470
|
+
_trySetBuybackPoolFor(revnetId, accountingContext.token);
|
|
470
471
|
}
|
|
471
472
|
}
|
|
472
473
|
}
|
|
473
474
|
|
|
475
|
+
/// @notice Try to configure a buyback pool for a terminal token. Silently catches failures (e.g., if the Uniswap V4
|
|
476
|
+
/// pool isn't initialized yet).
|
|
477
|
+
/// @param revnetId The ID of the revnet.
|
|
478
|
+
/// @param terminalToken The terminal token to configure a buyback pool for.
|
|
479
|
+
function _trySetBuybackPoolFor(uint256 revnetId, address terminalToken) internal {
|
|
480
|
+
// Normalize the terminal token (use WETH for native) and get the project token.
|
|
481
|
+
address normalizedTerminalToken = terminalToken == JBConstants.NATIVE_TOKEN
|
|
482
|
+
? address(IJBBuybackHook(address(BUYBACK_HOOK)).WETH())
|
|
483
|
+
: terminalToken;
|
|
484
|
+
address projectToken = address(CONTROLLER.TOKENS().tokenOf(revnetId));
|
|
485
|
+
|
|
486
|
+
// Sort currencies numerically for the pool key (lower address = currency0).
|
|
487
|
+
(Currency currency0, Currency currency1) = normalizedTerminalToken < projectToken
|
|
488
|
+
? (Currency.wrap(normalizedTerminalToken), Currency.wrap(projectToken))
|
|
489
|
+
: (Currency.wrap(projectToken), Currency.wrap(normalizedTerminalToken));
|
|
490
|
+
|
|
491
|
+
// Try to set the pool — if the pool isn't initialized in the PoolManager yet, this will revert and be caught.
|
|
492
|
+
try IJBBuybackHook(address(BUYBACK_HOOK))
|
|
493
|
+
.setPoolFor({
|
|
494
|
+
projectId: revnetId,
|
|
495
|
+
poolKey: PoolKey({
|
|
496
|
+
currency0: currency0,
|
|
497
|
+
currency1: currency1,
|
|
498
|
+
fee: DEFAULT_BUYBACK_POOL_FEE,
|
|
499
|
+
tickSpacing: DEFAULT_BUYBACK_TICK_SPACING,
|
|
500
|
+
hooks: IHooks(address(0))
|
|
501
|
+
}),
|
|
502
|
+
twapWindow: DEFAULT_BUYBACK_TWAP_WINDOW,
|
|
503
|
+
terminalToken: terminalToken
|
|
504
|
+
}) {}
|
|
505
|
+
catch {} // Pool may not be initialized yet — that's OK.
|
|
506
|
+
}
|
|
507
|
+
|
|
474
508
|
/// @notice Make a ruleset configuration for a revnet's stage.
|
|
475
509
|
/// @param baseCurrency The base currency of the revnet.
|
|
476
510
|
/// @param stageConfiguration The stage configuration to make a ruleset for.
|
|
@@ -696,6 +730,17 @@ contract REVDeployer is ERC2771Context, IREVDeployer, IJBRulesetDataHook, IJBCas
|
|
|
696
730
|
return revnetId;
|
|
697
731
|
}
|
|
698
732
|
|
|
733
|
+
/// @notice Burn any of a revnet's tokens held by this contract.
|
|
734
|
+
/// @dev Project tokens can end up here from reserved token distribution when splits don't sum to 100%.
|
|
735
|
+
/// @param revnetId The ID of the revnet whose tokens should be burned.
|
|
736
|
+
function burnHeldTokensOf(uint256 revnetId) external override {
|
|
737
|
+
uint256 balance = CONTROLLER.TOKENS().totalBalanceOf({holder: address(this), projectId: revnetId});
|
|
738
|
+
if (balance == 0) revert REVDeployer_NothingToBurn();
|
|
739
|
+
CONTROLLER.burnTokensOf({holder: address(this), projectId: revnetId, tokenCount: balance, memo: ""});
|
|
740
|
+
// slither-disable-next-line reentrancy-events
|
|
741
|
+
emit BurnHeldTokens(revnetId, balance, _msgSender());
|
|
742
|
+
}
|
|
743
|
+
|
|
699
744
|
/// @notice Deploy new suckers for an existing revnet.
|
|
700
745
|
/// @dev Only the revnet's split operator can deploy new suckers.
|
|
701
746
|
/// @param revnetId The ID of the revnet to deploy suckers for.
|
|
@@ -777,17 +822,6 @@ contract REVDeployer is ERC2771Context, IREVDeployer, IJBRulesetDataHook, IJBCas
|
|
|
777
822
|
return (revnetId, hook);
|
|
778
823
|
}
|
|
779
824
|
|
|
780
|
-
/// @notice Burn any of a revnet's tokens held by this contract.
|
|
781
|
-
/// @dev Project tokens can end up here from reserved token distribution when splits don't sum to 100%.
|
|
782
|
-
/// @param revnetId The ID of the revnet whose tokens should be burned.
|
|
783
|
-
function burnHeldTokensOf(uint256 revnetId) external override {
|
|
784
|
-
uint256 balance = CONTROLLER.TOKENS().totalBalanceOf({holder: address(this), projectId: revnetId});
|
|
785
|
-
if (balance == 0) revert REVDeployer_NothingToBurn();
|
|
786
|
-
CONTROLLER.burnTokensOf({holder: address(this), projectId: revnetId, tokenCount: balance, memo: ""});
|
|
787
|
-
// slither-disable-next-line reentrancy-events
|
|
788
|
-
emit BurnHeldTokens(revnetId, balance, _msgSender());
|
|
789
|
-
}
|
|
790
|
-
|
|
791
825
|
/// @notice Change a revnet's split operator.
|
|
792
826
|
/// @dev Only a revnet's current split operator can set a new split operator.
|
|
793
827
|
/// @param revnetId The ID of the revnet to set the split operator of.
|