From b8cba66d2c786588423f6e4f2cef109e57abbf3c Mon Sep 17 00:00:00 2001 From: ququzone Date: Mon, 9 Sep 2024 10:10:36 +0800 Subject: [PATCH] reward per project --- contracts/PeriodClaimVault.sol | 35 ++++++++++++++++++++-------------- test/TestPeriodClaimVault.ts | 21 +++++++++++--------- 2 files changed, 33 insertions(+), 23 deletions(-) diff --git a/contracts/PeriodClaimVault.sol b/contracts/PeriodClaimVault.sol index 41b8ee5..7984873 100644 --- a/contracts/PeriodClaimVault.sol +++ b/contracts/PeriodClaimVault.sol @@ -11,47 +11,52 @@ interface IioIDStore { contract PeriodClaimVault is OwnableUpgradeable { event Donation(address indexed donor, uint256 amount); event Withdraw(address indexed owner, address recipcient, uint256 amount); - event Initialize(uint256 period, uint256 rewardPerDevice); - event AddProject(uint256 projectId, address recipient, uint256 startTimestamp); + event Initialize(uint256 period); + event AddProject(uint256 projectId, uint256 rewardPerDevice, address recipient, uint256 startTimestamp); event RemoveProject(uint256 projectId); event Claim(uint256 projectId, address recipient, uint256 startTimestamp, uint256 endTimestamp, uint256 rewards); event ChangePeriod(uint256 batchSize); - event ChangeRewardPerDevice(uint256 rewardPerDevice); + event ChangeRewardPerDevice(uint256 projectId, uint256 rewardPerDevice); event ChangeRecipient(address indexed admin, uint256 projectId, address recipient); event SetInvalidDevice(uint256 projectId, uint256 amount); IioIDStore public ioIDStore; uint256 public period; - uint256 public rewardPerDevice; uint256 public projectNum; + mapping(uint256 => uint256) public rewardPerDevice; mapping(uint256 => address) public projectRecipient; mapping(uint256 => uint256) public projectInvalidDevice; mapping(uint256 => uint256) public lastClaimedTimestamp; - function initialize(address _ioIDStore, uint256 _rewardPerDevice) public initializer { + function initialize(address _ioIDStore) public initializer { require(_ioIDStore != address(0), "zero address"); - require(_rewardPerDevice > 0, "invalid reward per device"); __Ownable_init_unchained(); ioIDStore = IioIDStore(_ioIDStore); uint256 _period = 1 days; period = _period; - rewardPerDevice = _rewardPerDevice; - emit Initialize(_period, _rewardPerDevice); + emit Initialize(_period); } - function addProject(uint256 _projectId, address _recipient, uint256 _startTimestamp) external onlyOwner { + function addProject( + uint256 _projectId, + uint256 _rewardPerDevice, + address _recipient, + uint256 _startTimestamp + ) external onlyOwner { require(_recipient != address(0), "zero address"); + require(_rewardPerDevice > 0, "invalid reward per device"); require(_startTimestamp > block.timestamp, "invalid start timestamp"); require(projectRecipient[_projectId] == address(0), "already added"); require(ioIDStore.projectDeviceContract(_projectId) != address(0), "invalid project"); projectNum++; + rewardPerDevice[_projectId] = _rewardPerDevice; projectRecipient[_projectId] = _recipient; lastClaimedTimestamp[_projectId] = _startTimestamp; - emit AddProject(_projectId, _recipient, _startTimestamp); + emit AddProject(_projectId, _rewardPerDevice, _recipient, _startTimestamp); } function removeProject(uint256 _projectId) external onlyOwner { @@ -69,7 +74,7 @@ contract PeriodClaimVault is OwnableUpgradeable { require(_lastClaimedTimestamp + period <= block.timestamp, "claim too short"); uint256 _claimablePeriods = (block.timestamp - _lastClaimedTimestamp) / period; uint256 _rewards = _claimablePeriods * - rewardPerDevice * + rewardPerDevice[_projectId] * (ioIDStore.projectActivedAmount(_projectId) - projectInvalidDevice[_projectId]); require(address(this).balance >= _rewards, "insufficient fund"); lastClaimedTimestamp[_projectId] += (_claimablePeriods * period); @@ -87,11 +92,13 @@ contract PeriodClaimVault is OwnableUpgradeable { emit ChangePeriod(_period); } - function changeRewardPerDevice(uint256 _rewardPerDevice) external onlyOwner { + function changeRewardPerDevice(uint256 _projectId, uint256 _rewardPerDevice) external onlyOwner { require(_rewardPerDevice > 0, "invalid reward per device"); - rewardPerDevice = _rewardPerDevice; + require(projectRecipient[_projectId] != address(0), "invalid project"); + + rewardPerDevice[_projectId] = _rewardPerDevice; - emit ChangeRewardPerDevice(_rewardPerDevice); + emit ChangeRewardPerDevice(_projectId, _rewardPerDevice); } function setInvalidDevice(uint256 _projectId, uint256 _amount) external onlyOwner { diff --git a/test/TestPeriodClaimVault.ts b/test/TestPeriodClaimVault.ts index a607733..f3d4fcd 100644 --- a/test/TestPeriodClaimVault.ts +++ b/test/TestPeriodClaimVault.ts @@ -8,12 +8,11 @@ describe('PeriodClaimVault tests', function () { const ioIDStore = await ethers.deployContract('TestIoIDStore'); const vault = await ethers.deployContract('PeriodClaimVault'); - await vault.connect(owner).initialize(ioIDStore.target, ethers.parseEther('0.1')); + await vault.connect(owner).initialize(ioIDStore.target); expect(await vault.period()).to.equal(86400); - expect(await vault.rewardPerDevice()).to.equal(ethers.parseEther('0.1')); await expect(vault.connect(fakeRecipient).changePeriod(10)).to.revertedWith('Ownable: caller is not the owner'); - await expect(vault.connect(fakeRecipient).changeRewardPerDevice(10)).to.revertedWith( + await expect(vault.connect(fakeRecipient).changeRewardPerDevice(1, 10)).to.revertedWith( 'Ownable: caller is not the owner', ); await expect(vault.connect(fakeRecipient).changeRecipient(1, fakeRecipient.address)).to.revertedWith( @@ -36,9 +35,13 @@ describe('PeriodClaimVault tests', function () { const projectId = 1; const projectRecipient = '0x0000000000000000000000000000000000000100'; - await expect(vault.addProject(2, projectRecipient, startTimestamp)).to.revertedWith('invalid project'); - await vault.addProject(projectId, projectRecipient, startTimestamp); - await expect(vault.addProject(projectId, projectRecipient, startTimestamp)).to.revertedWith('already added'); + await expect(vault.addProject(2, ethers.parseEther('0.1'), projectRecipient, startTimestamp)).to.revertedWith( + 'invalid project', + ); + await vault.addProject(projectId, ethers.parseEther('0.1'), projectRecipient, startTimestamp); + await expect( + vault.addProject(projectId, ethers.parseEther('0.1'), projectRecipient, startTimestamp), + ).to.revertedWith('already added'); expect(await vault.lastClaimedTimestamp(projectId)).to.be.equals(startTimestamp); await expect(vault.claim(projectId)).to.revertedWith('claim too short'); @@ -49,7 +52,7 @@ describe('PeriodClaimVault tests', function () { await vault.donate({ value: ethers.parseEther('100') }); await vault.claim(projectId); expect(await ethers.provider.getBalance(projectRecipient)).to.be.equals( - (await ioIDStore.projectActivedAmount(projectId)) * (await vault.rewardPerDevice()), + (await ioIDStore.projectActivedAmount(projectId)) * (await vault.rewardPerDevice(projectId)), ); await expect(vault.claim(projectId)).to.revertedWith('claim too short'); @@ -60,14 +63,14 @@ describe('PeriodClaimVault tests', function () { await vault.claim(projectId); expect((await ethers.provider.getBalance(projectRecipient)) - balanceRecipient).to.be.equals( ((await ioIDStore.projectActivedAmount(projectId)) - (await vault.projectInvalidDevice(projectId))) * - (await vault.rewardPerDevice()), + (await vault.rewardPerDevice(projectId)), ); await time.increaseTo(startTimestamp + 86400 * 5 + 50000); await vault.connect(fakeRecipient).claim(projectId); expect((await ethers.provider.getBalance(projectRecipient)) - balanceRecipient).to.be.equals( ((await ioIDStore.projectActivedAmount(projectId)) - (await vault.projectInvalidDevice(projectId))) * - (await vault.rewardPerDevice()) * + (await vault.rewardPerDevice(projectId)) * BigInt(4), );