@rev-net/core-v6 0.0.29 → 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.
Files changed (77) hide show
  1. package/ADMINISTRATION.md +19 -9
  2. package/ARCHITECTURE.md +3 -0
  3. package/AUDIT_INSTRUCTIONS.md +11 -1
  4. package/CHANGELOG.md +26 -0
  5. package/README.md +1 -0
  6. package/RISKS.md +28 -4
  7. package/SKILLS.md +2 -1
  8. package/USER_JOURNEYS.md +28 -3
  9. package/package.json +8 -8
  10. package/references/operations.md +1 -1
  11. package/script/Deploy.s.sol +26 -4
  12. package/src/REVDeployer.sol +4 -2
  13. package/src/REVHiddenTokens.sol +149 -0
  14. package/src/REVLoans.sol +192 -199
  15. package/src/REVOwner.sol +51 -14
  16. package/src/interfaces/IREVHiddenTokens.sol +53 -0
  17. package/src/interfaces/IREVLoans.sol +8 -6
  18. package/test/REV.integrations.t.sol +12 -2
  19. package/test/REVAutoIssuanceFuzz.t.sol +12 -2
  20. package/test/REVDeployerRegressions.t.sol +14 -3
  21. package/test/REVInvincibility.t.sol +27 -8
  22. package/test/REVInvincibilityHandler.sol +1 -1
  23. package/test/REVLifecycle.t.sol +14 -3
  24. package/test/REVLoans.invariants.t.sol +15 -4
  25. package/test/REVLoansAttacks.t.sol +19 -7
  26. package/test/REVLoansFeeRecovery.t.sol +24 -13
  27. package/test/REVLoansFindings.t.sol +16 -5
  28. package/test/REVLoansRegressions.t.sol +15 -4
  29. package/test/REVLoansSourceFeeRecovery.t.sol +16 -5
  30. package/test/REVLoansSourced.t.sol +60 -25
  31. package/test/REVLoansUnSourced.t.sol +15 -4
  32. package/test/TestBurnHeldTokens.t.sol +14 -3
  33. package/test/TestCEIPattern.t.sol +19 -7
  34. package/test/TestCashOutCallerValidation.t.sol +15 -4
  35. package/test/TestConversionDocumentation.t.sol +14 -3
  36. package/test/TestCrossCurrencyReclaim.t.sol +14 -3
  37. package/test/TestCrossSourceReallocation.t.sol +15 -4
  38. package/test/TestERC2771MetaTx.t.sol +18 -5
  39. package/test/TestEmptyBuybackSpecs.t.sol +14 -3
  40. package/test/TestFlashLoanSurplus.t.sol +15 -4
  41. package/test/TestHiddenTokens.t.sol +431 -0
  42. package/test/TestHookArrayOOB.t.sol +14 -3
  43. package/test/TestLiquidationBehavior.t.sol +16 -5
  44. package/test/TestLoanSourceRotation.t.sol +20 -7
  45. package/test/TestLoansCashOutDelay.t.sol +18 -7
  46. package/test/TestLongTailEconomics.t.sol +14 -3
  47. package/test/TestLowFindings.t.sol +25 -9
  48. package/test/TestMixedFixes.t.sol +19 -8
  49. package/test/TestPermit2Signatures.t.sol +15 -4
  50. package/test/TestReallocationSandwich.t.sol +16 -4
  51. package/test/TestRevnetRegressions.t.sol +16 -5
  52. package/test/TestSplitWeightAdjustment.t.sol +16 -4
  53. package/test/TestSplitWeightE2E.t.sol +18 -4
  54. package/test/TestSplitWeightFork.t.sol +16 -3
  55. package/test/TestStageTransitionBorrowable.t.sol +14 -3
  56. package/test/TestSwapTerminalPermission.t.sol +14 -3
  57. package/test/TestUint112Overflow.t.sol +15 -4
  58. package/test/TestZeroAmountLoanGuard.t.sol +15 -4
  59. package/test/TestZeroRepayment.t.sol +15 -4
  60. package/test/audit/CodexPhantomSurplusTerminal.t.sol +367 -0
  61. package/test/audit/LoanIdOverflowGuard.t.sol +16 -5
  62. package/test/audit/NemesisOperatorDelegation.t.sol +289 -0
  63. package/test/fork/ForkTestBase.sol +18 -4
  64. package/test/fork/TestLoanBorrowFork.t.sol +2 -1
  65. package/test/fork/TestLoanERC20Fork.t.sol +4 -2
  66. package/test/fork/TestLoanTransferFork.t.sol +12 -2
  67. package/test/helpers/MaliciousContracts.sol +1 -1
  68. package/test/mock/MockBuybackCashOutRecorder.sol +2 -0
  69. package/test/mock/MockBuybackDataHook.sol +3 -1
  70. package/test/mock/MockBuybackDataHookMintPath.sol +2 -0
  71. package/test/mock/MockSuckerRegistry.sol +17 -0
  72. package/test/regression/TestBurnPermissionRequired.t.sol +16 -5
  73. package/test/regression/TestCashOutBuybackFeeLeak.t.sol +16 -3
  74. package/test/regression/TestCrossRevnetLiquidation.t.sol +14 -3
  75. package/test/regression/TestCumulativeLoanCounter.t.sol +15 -4
  76. package/test/regression/TestLiquidateGapHandling.t.sol +15 -4
  77. package/test/regression/TestZeroPriceFeed.t.sol +17 -6
@@ -0,0 +1,149 @@
1
+ // SPDX-License-Identifier: MIT
2
+ pragma solidity 0.8.28;
3
+
4
+ import {IJBController} from "@bananapus/core-v6/src/interfaces/IJBController.sol";
5
+ import {IJBPermissioned} from "@bananapus/core-v6/src/interfaces/IJBPermissioned.sol";
6
+ import {IJBPermissions} from "@bananapus/core-v6/src/interfaces/IJBPermissions.sol";
7
+ import {JBPermissioned} from "@bananapus/core-v6/src/abstract/JBPermissioned.sol";
8
+ import {JBPermissionIds} from "@bananapus/permission-ids-v6/src/JBPermissionIds.sol";
9
+ import {ERC2771Context} from "@openzeppelin/contracts/metatx/ERC2771Context.sol";
10
+ import {Context} from "@openzeppelin/contracts/utils/Context.sol";
11
+
12
+ import {IREVHiddenTokens} from "./interfaces/IREVHiddenTokens.sol";
13
+
14
+ /// @notice Allows revnet token holders to temporarily hide (burn) tokens, excluding them from totalSupply and
15
+ /// increasing cash-out value for remaining holders. Hidden tokens can be revealed (re-minted) at any time.
16
+ contract REVHiddenTokens is ERC2771Context, JBPermissioned, IREVHiddenTokens {
17
+ //*********************************************************************//
18
+ // --------------------------- custom errors ------------------------- //
19
+ //*********************************************************************//
20
+
21
+ error REVHiddenTokens_InsufficientHiddenBalance(uint256 hiddenBalance, uint256 requested);
22
+
23
+ //*********************************************************************//
24
+ // --------------- public immutable stored properties ---------------- //
25
+ //*********************************************************************//
26
+
27
+ /// @notice The controller that manages revnets using this contract.
28
+ IJBController public immutable override CONTROLLER;
29
+
30
+ //*********************************************************************//
31
+ // --------------------- public stored properties -------------------- //
32
+ //*********************************************************************//
33
+
34
+ /// @notice The number of tokens a holder has hidden for a given revnet.
35
+ /// @custom:param holder The address of the token holder.
36
+ /// @custom:param revnetId The ID of the revnet.
37
+ mapping(address holder => mapping(uint256 revnetId => uint256 count)) public override hiddenBalanceOf;
38
+
39
+ /// @notice The total number of hidden tokens for a revnet.
40
+ /// @custom:param revnetId The ID of the revnet.
41
+ mapping(uint256 revnetId => uint256 count) public override totalHiddenOf;
42
+
43
+ //*********************************************************************//
44
+ // -------------------------- constructor ---------------------------- //
45
+ //*********************************************************************//
46
+
47
+ /// @param controller The controller that manages revnets.
48
+ /// @param trustedForwarder The trusted forwarder for ERC-2771 meta-transactions.
49
+ constructor(
50
+ IJBController controller,
51
+ address trustedForwarder
52
+ )
53
+ ERC2771Context(trustedForwarder)
54
+ JBPermissioned(IJBPermissioned(address(controller)).PERMISSIONS())
55
+ {
56
+ CONTROLLER = controller;
57
+ }
58
+
59
+ //*********************************************************************//
60
+ // --------------------- external transactions ----------------------- //
61
+ //*********************************************************************//
62
+
63
+ /// @notice Hide tokens by burning them and tracking them for later reveal.
64
+ /// @dev The holder must have granted BURN_TOKENS permission to this contract.
65
+ /// @param revnetId The ID of the revnet whose tokens to hide.
66
+ /// @param tokenCount The number of tokens to hide.
67
+ /// @param holder The address whose tokens to hide.
68
+ function hideTokensOf(uint256 revnetId, uint256 tokenCount, address holder) external override {
69
+ // Only the holder or a permissioned operator can hide tokens.
70
+ _requirePermissionFrom({account: holder, projectId: revnetId, permissionId: JBPermissionIds.HIDE_TOKENS});
71
+
72
+ // Increment the holder's hidden balance.
73
+ hiddenBalanceOf[holder][revnetId] += tokenCount;
74
+
75
+ // Increment the revnet's total hidden count.
76
+ totalHiddenOf[revnetId] += tokenCount;
77
+
78
+ // Burn the tokens from the holder. The holder must have granted BURN_TOKENS permission.
79
+ // slither-disable-next-line reentrancy-events
80
+ CONTROLLER.burnTokensOf({holder: holder, projectId: revnetId, tokenCount: tokenCount, memo: ""});
81
+
82
+ emit HideTokens({revnetId: revnetId, tokenCount: tokenCount, holder: holder, caller: _msgSender()});
83
+ }
84
+
85
+ /// @notice Reveal previously hidden tokens by re-minting them.
86
+ /// @dev A delegated operator (with REVEAL_TOKENS permission) can set `beneficiary` to any address, directing
87
+ /// revealed tokens away from the holder. Grant this permission only to trusted operators.
88
+ /// @param revnetId The ID of the revnet whose tokens to reveal.
89
+ /// @param tokenCount The number of tokens to reveal.
90
+ /// @param beneficiary The address that will receive the revealed tokens.
91
+ /// @param holder The address whose hidden balance to decrement.
92
+ function revealTokensOf(
93
+ uint256 revnetId,
94
+ uint256 tokenCount,
95
+ address beneficiary,
96
+ address holder
97
+ )
98
+ external
99
+ override
100
+ {
101
+ // Only the holder or a permissioned operator can reveal tokens.
102
+ // Note: the operator controls `beneficiary`, so they can direct revealed tokens to any address.
103
+ _requirePermissionFrom({account: holder, projectId: revnetId, permissionId: JBPermissionIds.REVEAL_TOKENS});
104
+
105
+ uint256 hidden = hiddenBalanceOf[holder][revnetId];
106
+
107
+ // Make sure the holder has enough hidden tokens.
108
+ if (hidden < tokenCount) {
109
+ revert REVHiddenTokens_InsufficientHiddenBalance({hiddenBalance: hidden, requested: tokenCount});
110
+ }
111
+
112
+ // Decrement the holder's hidden balance.
113
+ hiddenBalanceOf[holder][revnetId] = hidden - tokenCount;
114
+
115
+ // Decrement the revnet's total hidden count.
116
+ totalHiddenOf[revnetId] -= tokenCount;
117
+
118
+ // Mint the tokens to the beneficiary without applying the reserved percent.
119
+ // slither-disable-next-line unused-return,reentrancy-events
120
+ CONTROLLER.mintTokensOf({
121
+ projectId: revnetId, tokenCount: tokenCount, beneficiary: beneficiary, memo: "", useReservedPercent: false
122
+ });
123
+
124
+ emit RevealTokens({
125
+ revnetId: revnetId, tokenCount: tokenCount, beneficiary: beneficiary, holder: holder, caller: _msgSender()
126
+ });
127
+ }
128
+
129
+ //*********************************************************************//
130
+ // ------------------------ internal overrides ----------------------- //
131
+ //*********************************************************************//
132
+
133
+ /// @dev Resolve the `_msgSender` conflict between `ERC2771Context` and `Context` (from `JBPermissioned`).
134
+ /// Prefer the ERC2771 version.
135
+ function _msgSender() internal view override(ERC2771Context, Context) returns (address) {
136
+ return ERC2771Context._msgSender();
137
+ }
138
+
139
+ /// @dev Resolve the `_msgData` conflict between `ERC2771Context` and `Context` (from `JBPermissioned`).
140
+ /// Prefer the ERC2771 version.
141
+ function _msgData() internal view override(ERC2771Context, Context) returns (bytes calldata) {
142
+ return ERC2771Context._msgData();
143
+ }
144
+
145
+ /// @dev Resolve the `_contextSuffixLength` conflict between `ERC2771Context` and `Context`.
146
+ function _contextSuffixLength() internal view override(ERC2771Context, Context) returns (uint256) {
147
+ return ERC2771Context._contextSuffixLength();
148
+ }
149
+ }