Skip to content

Commit a8bd777

Browse files
authored
Merge pull request #104 from NFTX-project/fee-distributor-add-guardians
FeeDistributor: inherit Pausable to add guardians
2 parents 03a6485 + ccaa37a commit a8bd777

File tree

3 files changed

+62
-51
lines changed

3 files changed

+62
-51
lines changed

src/NFTXFeeDistributorV3.sol

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
pragma solidity =0.8.15;
33

44
// inheriting
5-
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
5+
import {Pausable} from "@src/custom/Pausable.sol";
66
import {ReentrancyGuard} from "@openzeppelin/contracts/security/ReentrancyGuard.sol";
77

88
// libs
@@ -27,7 +27,7 @@ import {INFTXFeeDistributorV3} from "@src/interfaces/INFTXFeeDistributorV3.sol";
2727
*/
2828
contract NFTXFeeDistributorV3 is
2929
INFTXFeeDistributorV3,
30-
Ownable,
30+
Pausable,
3131
ReentrancyGuard
3232
{
3333
using SafeERC20 for IERC20;
@@ -44,6 +44,9 @@ contract NFTXFeeDistributorV3 is
4444
uint256 constant POOL_DEFAULT_ALLOC = 0.8 ether; // 80%
4545
uint256 constant INVENTORY_DEFAULT_ALLOC = 0.2 ether; // 20%
4646

47+
uint256 constant DISTRIBUTE_LOCK_ID = 0;
48+
uint256 constant DISTRIBUTE_VTOKENS_LOCK_ID = 1;
49+
4750
// =============================================================
4851
// VARIABLES
4952
// =============================================================
@@ -56,8 +59,6 @@ contract NFTXFeeDistributorV3 is
5659
uint256 public override allocTotal;
5760
FeeReceiver[] public override feeReceivers;
5861

59-
bool public override distributionPaused;
60-
6162
// =============================================================
6263
// CONSTRUCTOR
6364
// =============================================================
@@ -108,11 +109,14 @@ contract NFTXFeeDistributorV3 is
108109
* @inheritdoc INFTXFeeDistributorV3
109110
*/
110111
function distribute(uint256 vaultId) external override nonReentrant {
112+
onlyOwnerIfPaused(DISTRIBUTE_LOCK_ID);
113+
111114
INFTXVaultV3 vault = INFTXVaultV3(nftxVaultFactory.vault(vaultId));
112115

113116
uint256 wethBalance = WETH.balanceOf(address(this));
114117

115-
if (distributionPaused || allocTotal == 0) {
118+
uint256 _allocTotal = allocTotal;
119+
if (_allocTotal == 0) {
116120
WETH.transfer(treasury, wethBalance);
117121
return;
118122
}
@@ -124,7 +128,7 @@ contract NFTXFeeDistributorV3 is
124128

125129
uint256 wethAmountToSend = leftover +
126130
(wethBalance * feeReceiver.allocPoint) /
127-
allocTotal;
131+
_allocTotal;
128132

129133
bool tokenSent = _sendForReceiver(
130134
feeReceiver,
@@ -152,6 +156,8 @@ contract NFTXFeeDistributorV3 is
152156
address vToken,
153157
uint256 vTokenAmount
154158
) external {
159+
onlyOwnerIfPaused(DISTRIBUTE_VTOKENS_LOCK_ID);
160+
155161
if (msg.sender != address(nftxRouter)) revert SenderNotNFTXRouter();
156162

157163
uint256 liquidity = IUniswapV3Pool(pool).liquidity();
@@ -229,14 +235,6 @@ contract NFTXFeeDistributorV3 is
229235
emit NewNFTXRouter(address(nftxRouter_));
230236
}
231237

232-
/**
233-
* @inheritdoc INFTXFeeDistributorV3
234-
*/
235-
function pauseFeeDistribution(bool pause) external override onlyOwner {
236-
distributionPaused = pause;
237-
emit PauseDistribution(pause);
238-
}
239-
240238
/**
241239
* @inheritdoc INFTXFeeDistributorV3
242240
*/

src/interfaces/INFTXFeeDistributorV3.sol

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,6 @@ interface INFTXFeeDistributorV3 {
5555
ReceiverType receiverType
5656
);
5757

58-
function distributionPaused() external view returns (bool);
59-
6058
// =============================================================
6159
// EVENTS
6260
// =============================================================
@@ -115,7 +113,5 @@ interface INFTXFeeDistributorV3 {
115113

116114
function setNFTXRouter(INFTXRouter nftxRouter) external;
117115

118-
function pauseFeeDistribution(bool pause) external;
119-
120116
function rescueTokens(IERC20 token) external;
121117
}

test/NFTXFeeDistributorV3.t.sol

Lines changed: 50 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,27 @@ import {TickHelpers} from "@src/lib/TickHelpers.sol";
77
import {UniswapV3PoolUpgradeable, IUniswapV3Pool} from "@uni-core/UniswapV3PoolUpgradeable.sol";
88
import {INFTXRouter} from "@src/NFTXRouter.sol";
99
import {INFTXFeeDistributorV3} from "@src/interfaces/INFTXFeeDistributorV3.sol";
10+
import {Pausable} from "@src/custom/Pausable.sol";
1011

1112
import {TestBase} from "@test/TestBase.sol";
1213

1314
contract NFTXFeeDistributorV3Tests is TestBase {
15+
uint256 constant DISTRIBUTE_LOCK_ID = 0;
16+
uint256 constant DISTRIBUTE_VTOKENS_LOCK_ID = 1;
17+
1418
event AddFeeReceiver(address receiver, uint256 allocPoint);
1519
event UpdateFeeReceiverAlloc(address receiver, uint256 allocPoint);
1620
event UpdateFeeReceiverAddress(address oldReceiver, address newReceiver);
1721
event RemoveFeeReceiver(address receiver);
1822
event UpdateTreasuryAddress(address oldTreasury, address newTreasury);
1923
event PauseDistribution(bool paused);
2024

25+
// constructor
26+
27+
function test_feeDistributor_constructor() external {
28+
assertEq(feeDistributor.owner(), address(this));
29+
}
30+
2131
// UniswapV3FactoryUpgradeable#setFeeDistributor
2232

2333
function test_setFeeDistributor_RevertsForNonOwner() external {
@@ -52,27 +62,28 @@ contract NFTXFeeDistributorV3Tests is TestBase {
5262

5363
// FeeDistributor#distribute
5464

55-
function test_feeDistribuion_whenDistributionPaused() external {
65+
function test_feeDistribution_whenDistributionPaused() external {
5666
_mintPosition(1);
5767

58-
// Pause distribution
59-
feeDistributor.pauseFeeDistribution(true);
60-
assertEq(feeDistributor.distributionPaused(), true);
68+
// add to guardians
69+
feeDistributor.setIsGuardian(address(this), true);
6170

62-
uint256 preTreasuryWethBalance = weth.balanceOf(TREASURY);
71+
// Pause distribution
72+
feeDistributor.pause(DISTRIBUTE_LOCK_ID);
73+
assertEq(feeDistributor.isPaused(DISTRIBUTE_LOCK_ID), true);
6374

6475
uint256 wethFees = 2 ether;
6576

6677
// distribute fees
6778
weth.deposit{value: wethFees}();
6879
weth.transfer(address(feeDistributor), wethFees);
69-
feeDistributor.distribute(0);
7080

71-
uint256 postTreasuryWethBalance = weth.balanceOf(TREASURY);
72-
assertEq(postTreasuryWethBalance - preTreasuryWethBalance, wethFees);
81+
hoax(makeAddr("nonOwner"));
82+
vm.expectRevert(Pausable.Paused.selector);
83+
feeDistributor.distribute(0);
7384
}
7485

75-
function test_feeDistribuion_whenZeroAllocTotal() external {
86+
function test_feeDistribution_whenZeroAllocTotal() external {
7687
_mintPosition(1);
7788

7889
// Remove all receivers
@@ -271,6 +282,36 @@ contract NFTXFeeDistributorV3Tests is TestBase {
271282
console.log("ETH received", ethReceived);
272283
}
273284

285+
// FeeDistributor#distributeVTokensToPool
286+
287+
function test_distributeVTokensToPool_whenPaused() external {
288+
// minting so that Pool is deployed
289+
_mintPosition(1);
290+
291+
// add to guardians
292+
feeDistributor.setIsGuardian(address(this), true);
293+
294+
// Pause distribution
295+
feeDistributor.pause(DISTRIBUTE_VTOKENS_LOCK_ID);
296+
assertEq(feeDistributor.isPaused(DISTRIBUTE_VTOKENS_LOCK_ID), true);
297+
298+
(uint256 mintedVTokens, ) = _mintVToken({
299+
qty: 1,
300+
depositor: address(this),
301+
receiver: address(feeDistributor)
302+
});
303+
304+
address pool = nftxRouter.getPool(address(vtoken), DEFAULT_FEE_TIER);
305+
306+
hoax(makeAddr("nonOwner"));
307+
vm.expectRevert(Pausable.Paused.selector);
308+
feeDistributor.distributeVTokensToPool({
309+
pool: pool,
310+
vToken: address(vtoken),
311+
vTokenAmount: mintedVTokens
312+
});
313+
}
314+
274315
// FeeDistributor#setTreasuryAddress
275316

276317
function test_setTreasuryAddress_RevertsForNonOwner() external {
@@ -324,30 +365,6 @@ contract NFTXFeeDistributorV3Tests is TestBase {
324365
assertEq(postNFTXRouter, newNFTXRouter);
325366
}
326367

327-
// FeeDistributor#pauseFeeDistribution
328-
329-
function test_pauseFeeDistribution_RevertsForNonOwner() external {
330-
bool newPause = true;
331-
332-
hoax(makeAddr("nonOwner"));
333-
vm.expectRevert("Ownable: caller is not the owner");
334-
feeDistributor.pauseFeeDistribution(newPause);
335-
}
336-
337-
function test_pauseFeeDistribution_Success() external {
338-
bool preDistributionPaused = feeDistributor.distributionPaused();
339-
340-
bool newPause = !preDistributionPaused;
341-
342-
vm.expectEmit(false, false, false, true);
343-
emit PauseDistribution(newPause);
344-
feeDistributor.pauseFeeDistribution(newPause);
345-
346-
bool postDistributionPaused = feeDistributor.distributionPaused();
347-
348-
assertEq(postDistributionPaused, newPause);
349-
}
350-
351368
// FeeDistributor#rescueTokens
352369

353370
function test_rescueTokens_RevertsForNonOwner() external {

0 commit comments

Comments
 (0)