From c65bd71674eafc664d4e5ab07f672ddba3a3e3da Mon Sep 17 00:00:00 2001 From: Paterson <86971279+paterson1@users.noreply.github.com> Date: Thu, 17 Nov 2022 17:07:05 -0300 Subject: [PATCH 1/5] setPoolFee and setPoolPrivacy tests --- contracts/modules/staking/StakingPool.sol | 8 ++ test/unit/StakingPool/index.js | 2 + test/unit/StakingPool/setPoolFee.js | 96 +++++++++++++++++++++++ test/unit/StakingPool/setPoolPrivacy.js | 76 ++++++++++++++++++ 4 files changed, 182 insertions(+) create mode 100644 test/unit/StakingPool/setPoolFee.js create mode 100644 test/unit/StakingPool/setPoolPrivacy.js diff --git a/contracts/modules/staking/StakingPool.sol b/contracts/modules/staking/StakingPool.sol index 2a060fb864..9ad4428a1e 100644 --- a/contracts/modules/staking/StakingPool.sol +++ b/contracts/modules/staking/StakingPool.sol @@ -64,6 +64,10 @@ contract StakingPool is IStakingPool, ERC721 { // erc721 supply uint public totalSupply; + /* events */ + event PoolPrivacyChanged(address indexed src, bool isPrivate); + event PoolFeeChanged(address indexed src, uint newFee); + // tranche id => tranche data mapping(uint => Tranche) public tranches; @@ -1480,10 +1484,14 @@ function setProducts(StakedProductParam[] memory params) external onlyManager { // sstore deposits[0][trancheId] = feeDeposit; } + + emit PoolFeeChanged(msg.sender, newFee); } function setPoolPrivacy(bool _isPrivatePool) external onlyManager { isPrivatePool = _isPrivatePool; + + emit PoolPrivacyChanged(msg.sender, _isPrivatePool); } /* utils */ diff --git a/test/unit/StakingPool/index.js b/test/unit/StakingPool/index.js index 3518d0db55..22398cffcc 100644 --- a/test/unit/StakingPool/index.js +++ b/test/unit/StakingPool/index.js @@ -20,4 +20,6 @@ describe('StakingPool unit tests', function () { require('./calculateNewRewardShares'); require('./setProducts'); require('./depositTo'); + require('./setPoolFee'); + require('./setPoolPrivacy'); }); diff --git a/test/unit/StakingPool/setPoolFee.js b/test/unit/StakingPool/setPoolFee.js new file mode 100644 index 0000000000..1172fb37b4 --- /dev/null +++ b/test/unit/StakingPool/setPoolFee.js @@ -0,0 +1,96 @@ +const { ethers, expect } = require('hardhat'); +const { setEtherBalance } = require('../../utils/evm'); + +describe('setPoolFee', function () { + const product0 = { + productId: 0, + weight: 100, + initialPrice: '500', + targetPrice: '500', + }; + + const initializeParams = { + poolId: 0, + isPrivatePool: false, + initialPoolFee: 5, // 5% + maxPoolFee: 5, // 5% + productInitializationParams: [product0], + }; + + beforeEach(async function () { + const { + stakingPool, + cover, + accounts: { defaultSender: manager }, + } = this; + + const { poolId, initialPoolFee, maxPoolFee, productInitializationParams, isPrivatePool } = initializeParams; + + const coverSigner = await ethers.getImpersonatedSigner(cover.address); + await setEtherBalance(coverSigner.address, ethers.utils.parseEther('1')); + + await stakingPool + .connect(coverSigner) + .initialize(manager.address, isPrivatePool, initialPoolFee, maxPoolFee, productInitializationParams, poolId); + }); + + it('reverts if manager is not the caller', async function () { + const { + stakingPool, + accounts: { + defaultSender: manager, + nonMembers: [nonManager], + }, + } = this; + + await expect(stakingPool.connect(nonManager).setPoolFee(5)).to.be.revertedWith( + 'StakingPool: Only pool manager can call this function', + ); + await expect(stakingPool.connect(manager).setPoolFee(5)).to.not.be.reverted; + }); + + it('reverts if new fee exceeds max pool fee', async function () { + const { + stakingPool, + accounts: { defaultSender: manager }, + } = this; + + const { maxPoolFee } = initializeParams; + + await expect(stakingPool.connect(manager).setPoolFee(maxPoolFee + 1)).to.be.revertedWith( + 'StakingPool: new fee exceeds max fee', + ); + await expect(stakingPool.connect(manager).setPoolFee(maxPoolFee)).to.not.be.reverted; + }); + + it('updates pool fee', async function () { + const { + stakingPool, + accounts: { defaultSender: manager }, + } = this; + + const { maxPoolFee } = initializeParams; + + const newPoolFee = maxPoolFee - 2; + expect(await stakingPool.poolFee()).to.be.eq(maxPoolFee); + await stakingPool.connect(manager).setPoolFee(newPoolFee); + expect(await stakingPool.poolFee()).to.be.eq(newPoolFee); + }); + + xit('updates pool manager rewards', async function () {}); + + it('emits and PoolFeeChanged', async function () { + const { + stakingPool, + accounts: { defaultSender: manager }, + } = this; + + const { maxPoolFee } = initializeParams; + + const newPoolFee = maxPoolFee - 2; + + await expect(stakingPool.connect(manager).setPoolFee(newPoolFee)) + .to.emit(stakingPool, 'PoolFeeChanged') + .withArgs(manager.address, newPoolFee); + }); +}); diff --git a/test/unit/StakingPool/setPoolPrivacy.js b/test/unit/StakingPool/setPoolPrivacy.js new file mode 100644 index 0000000000..83f8904ae9 --- /dev/null +++ b/test/unit/StakingPool/setPoolPrivacy.js @@ -0,0 +1,76 @@ +const { ethers, expect } = require('hardhat'); +const { setEtherBalance } = require('../../utils/evm'); + +describe('setPoolPrivacy', function () { + const product0 = { + productId: 0, + weight: 100, + initialPrice: '500', + targetPrice: '500', + }; + + const initializeParams = { + poolId: 0, + isPrivatePool: false, + initialPoolFee: 5, // 5% + maxPoolFee: 5, // 5% + productInitializationParams: [product0], + }; + + beforeEach(async function () { + const { + stakingPool, + cover, + accounts: { defaultSender: manager }, + } = this; + + const { poolId, initialPoolFee, maxPoolFee, productInitializationParams, isPrivatePool } = initializeParams; + + const coverSigner = await ethers.getImpersonatedSigner(cover.address); + await setEtherBalance(coverSigner.address, ethers.utils.parseEther('1')); + + await stakingPool + .connect(coverSigner) + .initialize(manager.address, isPrivatePool, initialPoolFee, maxPoolFee, productInitializationParams, poolId); + }); + + it('reverts if manager is not the caller', async function () { + const { + stakingPool, + accounts: { + defaultSender: manager, + nonMembers: [nonManager], + }, + } = this; + + await expect(stakingPool.connect(nonManager).setPoolPrivacy(true)).to.be.revertedWith( + 'StakingPool: Only pool manager can call this function', + ); + await expect(stakingPool.connect(manager).setPoolPrivacy(true)).to.not.be.reverted; + }); + + it('updates isPrivatePool flag', async function () { + const { + stakingPool, + accounts: { defaultSender: manager }, + } = this; + + const isPrivateBefore = await stakingPool.isPrivatePool(); + await stakingPool.connect(manager).setPoolPrivacy(true); + const isPrivateAfter = await stakingPool.isPrivatePool(); + + expect(isPrivateAfter).to.not.eq(isPrivateBefore); + expect(isPrivateAfter).to.be.eq(true); + }); + + it('emits an event PoolPrivacyChanged', async function () { + const { + stakingPool, + accounts: { defaultSender: manager }, + } = this; + + await expect(stakingPool.connect(manager).setPoolPrivacy(true)) + .to.emit(stakingPool, 'PoolPrivacyChanged') + .withArgs(manager.address, true); + }); +}); From 40fb5c1966905b4603af3a7fbdbd1536f62f1a2d Mon Sep 17 00:00:00 2001 From: Paterson <86971279+paterson1@users.noreply.github.com> Date: Tue, 22 Nov 2022 16:49:15 -0300 Subject: [PATCH 2/5] rewards change on setPoolFee --- test/unit/StakingPool/index.js | 6 +-- test/unit/StakingPool/setPoolFee.js | 69 +++++++++++++++++++++++++++-- 2 files changed, 69 insertions(+), 6 deletions(-) diff --git a/test/unit/StakingPool/index.js b/test/unit/StakingPool/index.js index 22398cffcc..6d739b9709 100644 --- a/test/unit/StakingPool/index.js +++ b/test/unit/StakingPool/index.js @@ -1,7 +1,7 @@ const { takeSnapshot, revertToSnapshot } = require('../utils').evm; const setup = require('./setup'); -describe('StakingPool unit tests', function () { +describe.only('StakingPool unit tests', function () { before(setup); beforeEach(async function () { @@ -17,9 +17,9 @@ describe('StakingPool unit tests', function () { // require('./getPrices'); require('./constructor'); require('./initialize'); + require('./setPoolFee'); + require('./setPoolPrivacy'); require('./calculateNewRewardShares'); require('./setProducts'); require('./depositTo'); - require('./setPoolFee'); - require('./setPoolPrivacy'); }); diff --git a/test/unit/StakingPool/setPoolFee.js b/test/unit/StakingPool/setPoolFee.js index 1172fb37b4..1ec8694df1 100644 --- a/test/unit/StakingPool/setPoolFee.js +++ b/test/unit/StakingPool/setPoolFee.js @@ -1,5 +1,8 @@ +const { parseEther } = require('ethers/lib/utils'); const { ethers, expect } = require('hardhat'); -const { setEtherBalance } = require('../../utils/evm'); +const { daysToSeconds } = require('../../../lib/helpers'); +const { setEtherBalance, increaseTime } = require('../../utils/evm'); +const { getTranches } = require('./helpers'); describe('setPoolFee', function () { const product0 = { @@ -77,7 +80,67 @@ describe('setPoolFee', function () { expect(await stakingPool.poolFee()).to.be.eq(newPoolFee); }); - xit('updates pool manager rewards', async function () {}); + it('updates pool manager rewards', async function () { + const { + stakingPool, + cover, + accounts: { + defaultSender: manager, + members: [user], + }, + } = this; + + const { firstActiveTrancheId } = await getTranches(); + const amount = parseEther('100'); + const tokenId = 0; + const managerDepositId = 0; + const { initialPoolFee } = initializeParams; + const newPoolFee = initialPoolFee - 2; + + await stakingPool.connect(user).depositTo([ + { + amount, + trancheId: firstActiveTrancheId, + tokenId, + destination: ethers.constants.AddressZero, + }, + ]); + + // Generate rewards + const coverRequest = { + coverId: 0, + productId: 0, + amount: parseEther('100'), + period: daysToSeconds(30), + gracePeriod: daysToSeconds(30), + globalCapacityRatio: 20000, + capacityReductionRatio: 0, + rewardRatio: 10000, + }; + + const coverSigner = await ethers.getImpersonatedSigner(cover.address); + await stakingPool.connect(coverSigner).allocateStake(coverRequest); + + await increaseTime(daysToSeconds(25)); + + await stakingPool.updateTranches(true); + const accNxmPerRewardsShareBefore = await stakingPool.accNxmPerRewardsShare(); + + const managerDepositBefore = await stakingPool.deposits(managerDepositId, firstActiveTrancheId); + + await stakingPool.connect(manager).setPoolFee(newPoolFee); + + const managerDepositAfter = await stakingPool.deposits(managerDepositId, firstActiveTrancheId); + + const newLastAccNxmPerRewardShare = accNxmPerRewardsShareBefore.sub(managerDepositBefore.lastAccNxmPerRewardShare); + expect(managerDepositAfter.lastAccNxmPerRewardShare).to.not.equal(newLastAccNxmPerRewardShare); + expect(managerDepositAfter.pendingRewards).to.equal( + managerDepositAfter.lastAccNxmPerRewardShare.mul(managerDepositBefore.rewardsShares), + ); + expect(managerDepositAfter.rewardsShares).to.equal( + managerDepositBefore.rewardsShares.mul(newPoolFee).div(initialPoolFee), + ); + }); it('emits and PoolFeeChanged', async function () { const { @@ -87,7 +150,7 @@ describe('setPoolFee', function () { const { maxPoolFee } = initializeParams; - const newPoolFee = maxPoolFee - 2; + const newPoolFee = maxPoolFee - 1; await expect(stakingPool.connect(manager).setPoolFee(newPoolFee)) .to.emit(stakingPool, 'PoolFeeChanged') From b812b27faec03ae5c5937af4a28732087e858343 Mon Sep 17 00:00:00 2001 From: Paterson <86971279+paterson1@users.noreply.github.com> Date: Tue, 22 Nov 2022 16:50:32 -0300 Subject: [PATCH 3/5] remove only --- test/unit/StakingPool/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/unit/StakingPool/index.js b/test/unit/StakingPool/index.js index 6d739b9709..ba6db71f3c 100644 --- a/test/unit/StakingPool/index.js +++ b/test/unit/StakingPool/index.js @@ -1,7 +1,7 @@ const { takeSnapshot, revertToSnapshot } = require('../utils').evm; const setup = require('./setup'); -describe.only('StakingPool unit tests', function () { +describe('StakingPool unit tests', function () { before(setup); beforeEach(async function () { From 859f6defb606847eb3e0a3d6dd0e88879f8200a1 Mon Sep 17 00:00:00 2001 From: Paterson <86971279+paterson1@users.noreply.github.com> Date: Tue, 22 Nov 2022 18:42:51 -0300 Subject: [PATCH 4/5] fetch accNxmPerRewardShares after setPoolFee --- test/unit/StakingPool/setPoolFee.js | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/test/unit/StakingPool/setPoolFee.js b/test/unit/StakingPool/setPoolFee.js index 1ec8694df1..a7728d71a4 100644 --- a/test/unit/StakingPool/setPoolFee.js +++ b/test/unit/StakingPool/setPoolFee.js @@ -123,17 +123,15 @@ describe('setPoolFee', function () { await increaseTime(daysToSeconds(25)); - await stakingPool.updateTranches(true); - const accNxmPerRewardsShareBefore = await stakingPool.accNxmPerRewardsShare(); - const managerDepositBefore = await stakingPool.deposits(managerDepositId, firstActiveTrancheId); await stakingPool.connect(manager).setPoolFee(newPoolFee); + const accNxmPerRewardsShareBefore = await stakingPool.accNxmPerRewardsShare(); const managerDepositAfter = await stakingPool.deposits(managerDepositId, firstActiveTrancheId); const newLastAccNxmPerRewardShare = accNxmPerRewardsShareBefore.sub(managerDepositBefore.lastAccNxmPerRewardShare); - expect(managerDepositAfter.lastAccNxmPerRewardShare).to.not.equal(newLastAccNxmPerRewardShare); + expect(managerDepositAfter.lastAccNxmPerRewardShare).to.equal(newLastAccNxmPerRewardShare); expect(managerDepositAfter.pendingRewards).to.equal( managerDepositAfter.lastAccNxmPerRewardShare.mul(managerDepositBefore.rewardsShares), ); From a75a5fe84369b76f38285a5e6a55c4faa8dd9285 Mon Sep 17 00:00:00 2001 From: shark0der Date: Wed, 23 Nov 2022 11:15:29 +0200 Subject: [PATCH 5/5] Move staking pool events to interface and rename `src` to `manager` --- contracts/interfaces/IStakingPool.sol | 7 ++++++- contracts/modules/staking/StakingPool.sol | 4 ---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/contracts/interfaces/IStakingPool.sol b/contracts/interfaces/IStakingPool.sol index 915f889325..3042e30a89 100644 --- a/contracts/interfaces/IStakingPool.sol +++ b/contracts/interfaces/IStakingPool.sol @@ -144,5 +144,10 @@ interface IStakingPool { /* ========== EVENTS ========== */ - event StakeDeposited(address indexed user, uint256 amount, uint256 trancheId, uint256 tokenId); + event StakeDeposited(address indexed user, uint256 amount, uint256 trancheId, uint256 tokenId); + + event PoolPrivacyChanged(address indexed manager, bool isPrivate); + + event PoolFeeChanged(address indexed manager, uint newFee); + } diff --git a/contracts/modules/staking/StakingPool.sol b/contracts/modules/staking/StakingPool.sol index 9ad4428a1e..77e0a031a0 100644 --- a/contracts/modules/staking/StakingPool.sol +++ b/contracts/modules/staking/StakingPool.sol @@ -64,10 +64,6 @@ contract StakingPool is IStakingPool, ERC721 { // erc721 supply uint public totalSupply; - /* events */ - event PoolPrivacyChanged(address indexed src, bool isPrivate); - event PoolFeeChanged(address indexed src, uint newFee); - // tranche id => tranche data mapping(uint => Tranche) public tranches;