@@ -2,9 +2,8 @@ import { assert, expect } from "chai";
2
2
import { ethers } from "hardhat" ;
3
3
import { BigNumber , constants , Contract , utils } from "ethers" ;
4
4
import { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers" ;
5
- import * as blockTraveller from "./helpers/block-traveller" ;
5
+ import { advanceBlock , advanceBlockTo , pauseAutomine , resumeAutomine } from "./helpers/block-traveller" ;
6
6
7
- const { advanceBlockTo } = blockTraveller ;
8
7
const { parseEther } = utils ;
9
8
10
9
async function setupUsers (
@@ -17,9 +16,7 @@ async function setupUsers(
17
16
for ( const user of users ) {
18
17
await looksRareToken . connect ( admin ) . transfer ( user . address , parseEther ( "200" ) ) ;
19
18
await looksRareToken . connect ( user ) . approve ( feeSharingSystem . address , constants . MaxUint256 ) ;
20
-
21
19
await looksRareToken . connect ( user ) . approve ( aggregator . address , constants . MaxUint256 ) ;
22
-
23
20
await aggregator . connect ( user ) . deposit ( parseEther ( "100" ) ) ;
24
21
}
25
22
}
@@ -41,11 +38,10 @@ describe("AggregatorFeeSharing", () => {
41
38
42
39
beforeEach ( async ( ) => {
43
40
accounts = await ethers . getSigners ( ) ;
44
-
45
41
admin = accounts [ 0 ] ;
46
42
const tokenSplitter = accounts [ 19 ] ;
47
- const premintReceiver = admin ;
48
43
44
+ const premintReceiver = admin ;
49
45
const premintAmount = parseEther ( "6250" ) ;
50
46
const cap = parseEther ( "25000" ) ; // 25,000 tokens
51
47
@@ -95,7 +91,6 @@ describe("AggregatorFeeSharing", () => {
95
91
rewardToken . address ,
96
92
tokenDistributor . address
97
93
) ;
98
-
99
94
await feeSharingSystem . deployed ( ) ;
100
95
101
96
const minRewardDurationInBlocks = "30" ;
@@ -222,10 +217,10 @@ describe("AggregatorFeeSharing", () => {
222
217
// Advanced to the end of the first fee-sharing
223
218
await advanceBlockTo ( BigNumber . from ( await tokenDistributor . START_BLOCK ( ) ) . add ( "49" ) ) ;
224
219
225
- // Withdraw all
220
+ // User1 withdraws all
226
221
let tx = await aggregator . connect ( user1 ) . withdrawAll ( ) ;
227
222
228
- // 50 WETH sold for 100 LOOKS
223
+ // 50 WETH is sold for 100 LOOKS
229
224
await expect ( tx )
230
225
. to . emit ( aggregator , "ConversionToLOOKS" )
231
226
. withArgs ( parseEther ( "49.99999999999999980" ) , parseEther ( "99.9999999999999996" ) ) ;
@@ -297,7 +292,6 @@ describe("AggregatorFeeSharing", () => {
297
292
await rewardToken . connect ( admin ) . transfer ( aggregator . address , parseEther ( "0.999" ) ) ;
298
293
299
294
const tx = await aggregator . connect ( admin ) . harvestAndSellAndCompound ( ) ;
300
-
301
295
// Amount is equal to the threshold to trigger the selling
302
296
await expect ( tx ) . to . emit ( aggregator , "ConversionToLOOKS" ) . withArgs ( parseEther ( "0.999" ) , parseEther ( "0.999" ) ) ;
303
297
// Amount is lower than threshold to trigger the deposit
@@ -341,6 +335,20 @@ describe("AggregatorFeeSharing", () => {
341
335
await expect ( aggregator . connect ( admin ) . harvestAndSellAndCompound ( ) ) . to . be . revertedWith ( "Harvest: No share" ) ;
342
336
} ) ;
343
337
338
+ it ( "Cannot harvest if already harvested in same block" , async ( ) => {
339
+ const [ user1 , user2 , user3 ] = [ accounts [ 1 ] , accounts [ 2 ] , accounts [ 3 ] ] ;
340
+ await setupUsers ( feeSharingSystem , looksRareToken , aggregator , admin , [ user1 , user2 , user3 ] ) ;
341
+ await pauseAutomine ( ) ;
342
+ await aggregator . connect ( admin ) . harvestAndSellAndCompound ( ) ;
343
+ const tx = await aggregator . connect ( admin ) . harvestAndSellAndCompound ( ) ;
344
+ const pendingBlock = await ethers . provider . send ( "eth_getBlockByNumber" , [ "pending" , false ] ) ;
345
+ // Verify there are 2+ txs in the mempool
346
+ assert . isAtLeast ( pendingBlock . transactions . length , 2 ) ;
347
+ await advanceBlock ( ) ;
348
+ await resumeAutomine ( ) ;
349
+ await expect ( tx . wait ( ) ) . to . be . reverted ;
350
+ } ) ;
351
+
344
352
it ( "Faulty router doesn't throw revertion on harvesting operations if it fails to sell" , async ( ) => {
345
353
const MockFaultyUniswapV3Router = await ethers . getContractFactory ( "MockFaultyUniswapV3Router" ) ;
346
354
const faultyUniswapRouter = await MockFaultyUniswapV3Router . deploy ( ) ;
@@ -379,19 +387,35 @@ describe("AggregatorFeeSharing", () => {
379
387
await expect ( tx ) . to . emit ( aggregator , "HarvestStop" ) ;
380
388
} ) ;
381
389
382
- it ( "Owner can update threshold" , async ( ) => {
390
+ it ( "Owner can update threshold amount " , async ( ) => {
383
391
const tx = await aggregator . connect ( admin ) . updateThresholdAmount ( parseEther ( "5" ) ) ;
384
392
await expect ( tx ) . to . emit ( aggregator , "NewThresholdAmount" ) . withArgs ( parseEther ( "5" ) ) ;
385
393
} ) ;
386
394
395
+ it ( "Owner can adjust buffer block only within limits" , async ( ) => {
396
+ const MAXIMUM_HARVEST_BUFFER_BLOCKS = await aggregator . MAXIMUM_HARVEST_BUFFER_BLOCKS ( ) ;
397
+ const tx = await aggregator . connect ( admin ) . updateHarvestBufferBlocks ( MAXIMUM_HARVEST_BUFFER_BLOCKS ) ;
398
+ await expect ( tx ) . to . emit ( aggregator , "NewHarvestBufferBlocks" ) . withArgs ( MAXIMUM_HARVEST_BUFFER_BLOCKS ) ;
399
+
400
+ await expect (
401
+ aggregator . connect ( admin ) . updateHarvestBufferBlocks ( MAXIMUM_HARVEST_BUFFER_BLOCKS . add ( "1" ) )
402
+ ) . to . be . revertedWith ( "Owner: Must be below MAXIMUM_HARVEST_BUFFER_BLOCKS" ) ;
403
+ } ) ;
404
+
387
405
it ( "Owner can reset maximum allowance for LOOKS token" , async ( ) => {
388
406
const tx = await aggregator . connect ( admin ) . checkAndAdjustLOOKSTokenAllowanceIfRequired ( ) ;
389
-
390
407
await expect ( tx )
391
408
. to . emit ( looksRareToken , "Approval" )
392
409
. withArgs ( aggregator . address , feeSharingSystem . address , constants . MaxUint256 ) ;
393
410
} ) ;
394
411
412
+ it ( "Owner can reset maximum allowance for reward token" , async ( ) => {
413
+ const tx = await aggregator . connect ( admin ) . checkAndAdjustRewardTokenAllowanceIfRequired ( ) ;
414
+ await expect ( tx )
415
+ . to . emit ( rewardToken , "Approval" )
416
+ . withArgs ( aggregator . address , uniswapRouter . address , constants . MaxUint256 ) ;
417
+ } ) ;
418
+
395
419
it ( "Owner can pause/unpause" , async ( ) => {
396
420
let tx = await aggregator . connect ( admin ) . pause ( ) ;
397
421
await expect ( tx ) . to . emit ( aggregator , "Paused" ) ;
@@ -413,6 +437,14 @@ describe("AggregatorFeeSharing", () => {
413
437
) ;
414
438
} ) ;
415
439
440
+ it ( "Owner can update minPriceLOOKSInWETH" , async ( ) => {
441
+ // 1 LOOKS is at least equal to 0.01 WETH
442
+ // 1 WETH is at most equal to 100 LOOKS
443
+ const tx = await aggregator . connect ( admin ) . updateMinPriceOfLOOKSInWETH ( parseEther ( "0.01" ) ) ;
444
+ await expect ( tx ) . to . emit ( aggregator , "NewMinimumPriceOfLOOKSInWETH" ) . withArgs ( parseEther ( "0.01" ) ) ;
445
+ assert . deepEqual ( await aggregator . minPriceLOOKSInWETH ( ) , parseEther ( "0.01" ) ) ;
446
+ } ) ;
447
+
416
448
it ( "Only owner can call functions for onlyOwner" , async ( ) => {
417
449
const [ user1 , user2 , user3 ] = [ accounts [ 1 ] , accounts [ 2 ] , accounts [ 3 ] ] ;
418
450
await setupUsers ( feeSharingSystem , looksRareToken , aggregator , admin , [ user1 , user2 , user3 ] ) ;
@@ -426,14 +458,19 @@ describe("AggregatorFeeSharing", () => {
426
458
await expect ( aggregator . connect ( user1 ) . updateThresholdAmount ( "10" ) ) . to . be . revertedWith (
427
459
"Ownable: caller is not the owner"
428
460
) ;
461
+ await expect ( aggregator . connect ( user1 ) . updateMinPriceOfLOOKSInWETH ( parseEther ( "0.01" ) ) ) . to . be . revertedWith (
462
+ "Ownable: caller is not the owner"
463
+ ) ;
429
464
await expect ( aggregator . connect ( user1 ) . pause ( ) ) . to . be . revertedWith ( "Ownable: caller is not the owner" ) ;
430
465
await expect ( aggregator . connect ( user1 ) . unpause ( ) ) . to . be . revertedWith ( "Ownable: caller is not the owner" ) ;
431
466
await expect ( aggregator . connect ( user1 ) . startHarvest ( ) ) . to . be . revertedWith ( "Ownable: caller is not the owner" ) ;
432
467
await expect ( aggregator . connect ( user1 ) . stopHarvest ( ) ) . to . be . revertedWith ( "Ownable: caller is not the owner" ) ;
433
468
await expect ( aggregator . connect ( user1 ) . checkAndAdjustLOOKSTokenAllowanceIfRequired ( ) ) . to . be . revertedWith (
434
469
"Ownable: caller is not the owner"
435
470
) ;
436
-
471
+ await expect ( aggregator . connect ( user1 ) . checkAndAdjustRewardTokenAllowanceIfRequired ( ) ) . to . be . revertedWith (
472
+ "Ownable: caller is not the owner"
473
+ ) ;
437
474
await expect ( aggregator . connect ( user1 ) . stopHarvest ( ) ) . to . be . revertedWith ( "Ownable: caller is not the owner" ) ;
438
475
} ) ;
439
476
} ) ;
0 commit comments