From f86562779965796039f3ea20d47124ba612fbadc Mon Sep 17 00:00:00 2001 From: trizin <25263018+trizin@users.noreply.github.com> Date: Sat, 5 Aug 2023 16:45:11 +0300 Subject: [PATCH 01/30] Hide stake amounts for prediction epoch & allow predictoors modify their stake amount --- contracts/templates/ERC20Template3.sol | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/contracts/templates/ERC20Template3.sol b/contracts/templates/ERC20Template3.sol index 52ae3426..aa7c65c2 100644 --- a/contracts/templates/ERC20Template3.sol +++ b/contracts/templates/ERC20Template3.sol @@ -957,6 +957,8 @@ contract ERC20Template3 is ) public view returns (uint256, uint256) { _checkUserAuthorization(_userAuth); require(isValidSubscription(_userAuth.userAddress), "No subscription"); + require(toEpochStart(epoch_start) == epoch_start, "invalid epoch"); + require(soonestEpochToPredict(epoch_start) != epoch_start, "predictions not closed") return (roundSumStakesUp[epoch_start], roundSumStakes[epoch_start]); } @@ -996,8 +998,17 @@ contract ERC20Template3 is emit PredictionSubmitted(msg.sender, epoch_start, stake); if (submittedPredval(epoch_start, msg.sender)) { + uint256 oldStake = predictions[epoch_start][msg.sender].stake; + if (stake > oldStake) { + uint256 payment = stake - oldStake; + IERC20(stakeToken).safeTransferFrom(msg.sender, address(this), payment); + } else if (stake < oldStake) { + uint256 refund = oldStake - stake; + IERC20(stakeToken).safeTransferFrom(address(this), msg.sender, payment); + } require(predictions[epoch_start][msg.sender].stake == stake, "cannot modify stake amt"); predictions[epoch_start][msg.sender].predictedValue = predictedValue; + predictions[epoch_start][msg.sender].stake = stake; return; } predictions[epoch_start][msg.sender] = Prediction( From 82ffeca3c91d07afaed8fcad253616a09b6be7b2 Mon Sep 17 00:00:00 2001 From: trizin <25263018+trizin@users.noreply.github.com> Date: Sat, 5 Aug 2023 16:46:37 +0300 Subject: [PATCH 02/30] Fix --- contracts/templates/ERC20Template3.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/templates/ERC20Template3.sol b/contracts/templates/ERC20Template3.sol index aa7c65c2..b6e4b376 100644 --- a/contracts/templates/ERC20Template3.sol +++ b/contracts/templates/ERC20Template3.sol @@ -958,7 +958,7 @@ contract ERC20Template3 is _checkUserAuthorization(_userAuth); require(isValidSubscription(_userAuth.userAddress), "No subscription"); require(toEpochStart(epoch_start) == epoch_start, "invalid epoch"); - require(soonestEpochToPredict(epoch_start) != epoch_start, "predictions not closed") + require(soonestEpochToPredict(block.timestamp) < epoch_start, "predictions not closed") return (roundSumStakesUp[epoch_start], roundSumStakes[epoch_start]); } From a9fc804d422891486d2fab9bf180baf8e19d14f2 Mon Sep 17 00:00:00 2001 From: trizin <25263018+trizin@users.noreply.github.com> Date: Sat, 5 Aug 2023 16:47:15 +0300 Subject: [PATCH 03/30] Fix --- contracts/templates/ERC20Template3.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/templates/ERC20Template3.sol b/contracts/templates/ERC20Template3.sol index b6e4b376..f0e42ea6 100644 --- a/contracts/templates/ERC20Template3.sol +++ b/contracts/templates/ERC20Template3.sol @@ -958,7 +958,7 @@ contract ERC20Template3 is _checkUserAuthorization(_userAuth); require(isValidSubscription(_userAuth.userAddress), "No subscription"); require(toEpochStart(epoch_start) == epoch_start, "invalid epoch"); - require(soonestEpochToPredict(block.timestamp) < epoch_start, "predictions not closed") + require(soonestEpochToPredict(curEpoch()) < epoch_start, "predictions not closed") return (roundSumStakesUp[epoch_start], roundSumStakes[epoch_start]); } From a9a8d7b3f82141ed7d779b922a203e63c283136c Mon Sep 17 00:00:00 2001 From: trizin <25263018+trizin@users.noreply.github.com> Date: Sat, 5 Aug 2023 16:47:50 +0300 Subject: [PATCH 04/30] Fix --- contracts/templates/ERC20Template3.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/templates/ERC20Template3.sol b/contracts/templates/ERC20Template3.sol index f0e42ea6..1c7ce363 100644 --- a/contracts/templates/ERC20Template3.sol +++ b/contracts/templates/ERC20Template3.sol @@ -958,7 +958,7 @@ contract ERC20Template3 is _checkUserAuthorization(_userAuth); require(isValidSubscription(_userAuth.userAddress), "No subscription"); require(toEpochStart(epoch_start) == epoch_start, "invalid epoch"); - require(soonestEpochToPredict(curEpoch()) < epoch_start, "predictions not closed") + require(soonestEpochToPredict(curEpoch()) > epoch_start, "predictions not closed") return (roundSumStakesUp[epoch_start], roundSumStakes[epoch_start]); } From ba6b777fbc3d426def193802de0d048d292d6041 Mon Sep 17 00:00:00 2001 From: trizin <25263018+trizin@users.noreply.github.com> Date: Sat, 5 Aug 2023 16:51:23 +0300 Subject: [PATCH 05/30] Update duplicate prediction tests --- test/unit/datatokens/ERC20Template3.test.js | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/test/unit/datatokens/ERC20Template3.test.js b/test/unit/datatokens/ERC20Template3.test.js index e257029e..5f876e0c 100644 --- a/test/unit/datatokens/ERC20Template3.test.js +++ b/test/unit/datatokens/ERC20Template3.test.js @@ -845,15 +845,15 @@ describe("ERC20Template3", () => { prediction = await erc20Token.getPrediction(soonestEpochToPredict, owner.address, userAuth); expect(prediction.predictedValue).to.be.eq(!predictedValue); - await expectRevert( - erc20Token.submitPredval(predictedValue, stake + 1, soonestEpochToPredict), - "cannot modify stake" - ); - - await expectRevert( - erc20Token.submitPredval(predictedValue, stake - 1, soonestEpochToPredict), - "cannot modify stake" - ); + let mockErc20BalanceBefore = await mockErc20.balanceOf(owner.address); + await erc20Token.submitPredval(predictedValue, stake + 1, soonestEpochToPredict); + let mockErc20BalanceAfter = await mockErc20.balanceOf(owner.address); + expect(mockErc20BalanceAfter).to.equal(mockErc20BalanceBefore.add(-1)) + + mockErc20BalanceBefore = await mockErc20.balanceOf(owner.address); + await erc20Token.submitPredval(predictedValue, stake - 1, soonestEpochToPredict), + mockErc20BalanceAfter = await mockErc20.balanceOf(owner.address); + expect(mockErc20BalanceAfter).to.equal(mockErc20BalanceBefore.add(1)) }); it("#pausePredictions - should pause and resume predictions", async () => { await erc20Token.pausePredictions(); From eace40b7178920b40f096cef6021bec168263da7 Mon Sep 17 00:00:00 2001 From: trizin <25263018+trizin@users.noreply.github.com> Date: Sat, 5 Aug 2023 16:53:31 +0300 Subject: [PATCH 06/30] Update aggpredval test --- test/unit/datatokens/ERC20Template3.test.js | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/test/unit/datatokens/ERC20Template3.test.js b/test/unit/datatokens/ERC20Template3.test.js index 5f876e0c..2115e8d3 100644 --- a/test/unit/datatokens/ERC20Template3.test.js +++ b/test/unit/datatokens/ERC20Template3.test.js @@ -1191,7 +1191,10 @@ describe("ERC20Template3", () => { let soonestEpochToPredict = await erc20Token.soonestEpochToPredict(await blocktimestamp()); const userAuth = await authorize(user2.address) - const [numer, denom] = await erc20Token.connect(user2).getAggPredval(soonestEpochToPredict, userAuth); + await expectRevert(erc20Token.connect(user2).getAggPredval(soonestEpochToPredict, userAuth), "predictions not closed"); + + let curEpoch = await erc20Token.curEpoch(); + const [numer, denom] = await erc20Token.connect(user2).getAggPredval(curEpoch, userAuth); expect(numer).to.be.eq(0); expect(denom).to.be.eq(0); @@ -1201,7 +1204,9 @@ describe("ERC20Template3", () => { await mockErc20.transfer(user3.address, stake); await mockErc20.connect(user3).approve(erc20Token.address, stake); await erc20Token.connect(user3).submitPredval(predictedValue, stake, soonestEpochToPredict); - + + fastForward(secondsPerEpoch) + let curEpoch = await erc20Token.curEpoch(); const [numer2, denom2] = await erc20Token.connect(user2).getAggPredval(soonestEpochToPredict, userAuth); expect(numer2).to.be.eq(web3.utils.toWei("1")); expect(denom2).to.be.eq(web3.utils.toWei("1")); From a0053360f494b1855b5f89d667e53c8454363022 Mon Sep 17 00:00:00 2001 From: trizin <25263018+trizin@users.noreply.github.com> Date: Sat, 5 Aug 2023 16:54:22 +0300 Subject: [PATCH 07/30] Fix --- contracts/templates/ERC20Template3.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/templates/ERC20Template3.sol b/contracts/templates/ERC20Template3.sol index 1c7ce363..c4944038 100644 --- a/contracts/templates/ERC20Template3.sol +++ b/contracts/templates/ERC20Template3.sol @@ -958,7 +958,7 @@ contract ERC20Template3 is _checkUserAuthorization(_userAuth); require(isValidSubscription(_userAuth.userAddress), "No subscription"); require(toEpochStart(epoch_start) == epoch_start, "invalid epoch"); - require(soonestEpochToPredict(curEpoch()) > epoch_start, "predictions not closed") + require(soonestEpochToPredict(curEpoch()) > epoch_start, "predictions not closed"); return (roundSumStakesUp[epoch_start], roundSumStakes[epoch_start]); } From 0ee2bb8e167f547db91fb5cfc3aa66584e2f6733 Mon Sep 17 00:00:00 2001 From: trizin <25263018+trizin@users.noreply.github.com> Date: Sat, 5 Aug 2023 17:02:36 +0300 Subject: [PATCH 08/30] Fix --- contracts/templates/ERC20Template3.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/templates/ERC20Template3.sol b/contracts/templates/ERC20Template3.sol index c4944038..df144626 100644 --- a/contracts/templates/ERC20Template3.sol +++ b/contracts/templates/ERC20Template3.sol @@ -1004,7 +1004,7 @@ contract ERC20Template3 is IERC20(stakeToken).safeTransferFrom(msg.sender, address(this), payment); } else if (stake < oldStake) { uint256 refund = oldStake - stake; - IERC20(stakeToken).safeTransferFrom(address(this), msg.sender, payment); + IERC20(stakeToken).safeTransferFrom(address(this), msg.sender, refund); } require(predictions[epoch_start][msg.sender].stake == stake, "cannot modify stake amt"); predictions[epoch_start][msg.sender].predictedValue = predictedValue; From 9a7fa6b048bf8e98df960fcd6646377fc3df9f2e Mon Sep 17 00:00:00 2001 From: trizin <25263018+trizin@users.noreply.github.com> Date: Sat, 5 Aug 2023 17:03:44 +0300 Subject: [PATCH 09/30] Add getTotalStake function --- contracts/templates/ERC20Template3.sol | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/contracts/templates/ERC20Template3.sol b/contracts/templates/ERC20Template3.sol index df144626..69c04536 100644 --- a/contracts/templates/ERC20Template3.sol +++ b/contracts/templates/ERC20Template3.sol @@ -951,6 +951,7 @@ contract ERC20Template3 is bytes32 s; // s of provider signed message uint256 validUntil; } + function getAggPredval( uint256 epoch_start, userAuth calldata _userAuth @@ -962,6 +963,13 @@ contract ERC20Template3 is return (roundSumStakesUp[epoch_start], roundSumStakes[epoch_start]); } + function getTotalStake( + uint256 epoch_start + ) public view returns (uint256, uint256) { + require(toEpochStart(epoch_start) == epoch_start, "invalid epoch"); + return roundSumStakesUp[epoch_start] + roundSumStakes[epoch_start]; + } + function getsubscriptionRevenueAtEpoch( uint256 epoch_start ) public view returns (uint256) { From 60149d82ba6d9d95758829981454ec7c49dcf28a Mon Sep 17 00:00:00 2001 From: trizin <25263018+trizin@users.noreply.github.com> Date: Sat, 5 Aug 2023 17:05:33 +0300 Subject: [PATCH 10/30] Require predictions not closed --- contracts/templates/ERC20Template3.sol | 1 + 1 file changed, 1 insertion(+) diff --git a/contracts/templates/ERC20Template3.sol b/contracts/templates/ERC20Template3.sol index 69c04536..8243eeb0 100644 --- a/contracts/templates/ERC20Template3.sol +++ b/contracts/templates/ERC20Template3.sol @@ -967,6 +967,7 @@ contract ERC20Template3 is uint256 epoch_start ) public view returns (uint256, uint256) { require(toEpochStart(epoch_start) == epoch_start, "invalid epoch"); + require(soonestEpochToPredict(curEpoch()) > epoch_start, "predictions not closed"); return roundSumStakesUp[epoch_start] + roundSumStakes[epoch_start]; } From 92d024814c5fbad91fbddd80e3d447afd335ebcc Mon Sep 17 00:00:00 2001 From: trizin <25263018+trizin@users.noreply.github.com> Date: Sat, 5 Aug 2023 17:06:08 +0300 Subject: [PATCH 11/30] Fix --- contracts/templates/ERC20Template3.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/templates/ERC20Template3.sol b/contracts/templates/ERC20Template3.sol index 8243eeb0..56b14054 100644 --- a/contracts/templates/ERC20Template3.sol +++ b/contracts/templates/ERC20Template3.sol @@ -965,7 +965,7 @@ contract ERC20Template3 is function getTotalStake( uint256 epoch_start - ) public view returns (uint256, uint256) { + ) public view returns uint256 { require(toEpochStart(epoch_start) == epoch_start, "invalid epoch"); require(soonestEpochToPredict(curEpoch()) > epoch_start, "predictions not closed"); return roundSumStakesUp[epoch_start] + roundSumStakes[epoch_start]; From 68891b81d7e8ef2e727d7f776cb9b711297916b1 Mon Sep 17 00:00:00 2001 From: trizin <25263018+trizin@users.noreply.github.com> Date: Sat, 5 Aug 2023 17:06:33 +0300 Subject: [PATCH 12/30] Fix --- contracts/templates/ERC20Template3.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/templates/ERC20Template3.sol b/contracts/templates/ERC20Template3.sol index 56b14054..49432e30 100644 --- a/contracts/templates/ERC20Template3.sol +++ b/contracts/templates/ERC20Template3.sol @@ -968,7 +968,7 @@ contract ERC20Template3 is ) public view returns uint256 { require(toEpochStart(epoch_start) == epoch_start, "invalid epoch"); require(soonestEpochToPredict(curEpoch()) > epoch_start, "predictions not closed"); - return roundSumStakesUp[epoch_start] + roundSumStakes[epoch_start]; + return roundSumStakes[epoch_start]; } function getsubscriptionRevenueAtEpoch( From 0f928ffe25cd8764573faf17cc59686278efd474 Mon Sep 17 00:00:00 2001 From: trizin <25263018+trizin@users.noreply.github.com> Date: Sat, 5 Aug 2023 17:10:17 +0300 Subject: [PATCH 13/30] Fix --- contracts/templates/ERC20Template3.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/templates/ERC20Template3.sol b/contracts/templates/ERC20Template3.sol index 49432e30..39b4f544 100644 --- a/contracts/templates/ERC20Template3.sol +++ b/contracts/templates/ERC20Template3.sol @@ -965,7 +965,7 @@ contract ERC20Template3 is function getTotalStake( uint256 epoch_start - ) public view returns uint256 { + ) public view returns (uint256) { require(toEpochStart(epoch_start) == epoch_start, "invalid epoch"); require(soonestEpochToPredict(curEpoch()) > epoch_start, "predictions not closed"); return roundSumStakes[epoch_start]; From e0f18bf2b048a89379483d3d0d81716506ceb76a Mon Sep 17 00:00:00 2001 From: trizin <25263018+trizin@users.noreply.github.com> Date: Sat, 5 Aug 2023 17:19:41 +0300 Subject: [PATCH 14/30] Fix --- test/unit/datatokens/ERC20Template3.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/unit/datatokens/ERC20Template3.test.js b/test/unit/datatokens/ERC20Template3.test.js index 2115e8d3..cbbc26b6 100644 --- a/test/unit/datatokens/ERC20Template3.test.js +++ b/test/unit/datatokens/ERC20Template3.test.js @@ -1206,7 +1206,7 @@ describe("ERC20Template3", () => { await erc20Token.connect(user3).submitPredval(predictedValue, stake, soonestEpochToPredict); fastForward(secondsPerEpoch) - let curEpoch = await erc20Token.curEpoch(); + curEpoch = await erc20Token.curEpoch(); const [numer2, denom2] = await erc20Token.connect(user2).getAggPredval(soonestEpochToPredict, userAuth); expect(numer2).to.be.eq(web3.utils.toWei("1")); expect(denom2).to.be.eq(web3.utils.toWei("1")); From 53fbd6afc0dd2a6b86a1081c7609f676f5f9166a Mon Sep 17 00:00:00 2001 From: trizin <25263018+trizin@users.noreply.github.com> Date: Sat, 5 Aug 2023 17:26:37 +0300 Subject: [PATCH 15/30] Remove require --- contracts/templates/ERC20Template3.sol | 1 - 1 file changed, 1 deletion(-) diff --git a/contracts/templates/ERC20Template3.sol b/contracts/templates/ERC20Template3.sol index 39b4f544..f34f8a4c 100644 --- a/contracts/templates/ERC20Template3.sol +++ b/contracts/templates/ERC20Template3.sol @@ -1015,7 +1015,6 @@ contract ERC20Template3 is uint256 refund = oldStake - stake; IERC20(stakeToken).safeTransferFrom(address(this), msg.sender, refund); } - require(predictions[epoch_start][msg.sender].stake == stake, "cannot modify stake amt"); predictions[epoch_start][msg.sender].predictedValue = predictedValue; predictions[epoch_start][msg.sender].stake = stake; return; From 87871b2a2ad8c4eb1da5cc38365a3de52c379c3a Mon Sep 17 00:00:00 2001 From: trizin <25263018+trizin@users.noreply.github.com> Date: Sat, 5 Aug 2023 17:27:13 +0300 Subject: [PATCH 16/30] Fix --- test/unit/datatokens/ERC20Template3.test.js | 1 + 1 file changed, 1 insertion(+) diff --git a/test/unit/datatokens/ERC20Template3.test.js b/test/unit/datatokens/ERC20Template3.test.js index cbbc26b6..b7d4cfd3 100644 --- a/test/unit/datatokens/ERC20Template3.test.js +++ b/test/unit/datatokens/ERC20Template3.test.js @@ -1205,6 +1205,7 @@ describe("ERC20Template3", () => { await mockErc20.connect(user3).approve(erc20Token.address, stake); await erc20Token.connect(user3).submitPredval(predictedValue, stake, soonestEpochToPredict); + const secondsPerEpoch = await erc20Token.secondsPerEpoch(); fastForward(secondsPerEpoch) curEpoch = await erc20Token.curEpoch(); const [numer2, denom2] = await erc20Token.connect(user2).getAggPredval(soonestEpochToPredict, userAuth); From 32f89119710de31152c66033b071800cdf5c1ba7 Mon Sep 17 00:00:00 2001 From: trizin <25263018+trizin@users.noreply.github.com> Date: Sat, 5 Aug 2023 18:22:59 +0300 Subject: [PATCH 17/30] Fix approval --- test/unit/datatokens/ERC20Template3.test.js | 1 + 1 file changed, 1 insertion(+) diff --git a/test/unit/datatokens/ERC20Template3.test.js b/test/unit/datatokens/ERC20Template3.test.js index b7d4cfd3..efdbbe02 100644 --- a/test/unit/datatokens/ERC20Template3.test.js +++ b/test/unit/datatokens/ERC20Template3.test.js @@ -845,6 +845,7 @@ describe("ERC20Template3", () => { prediction = await erc20Token.getPrediction(soonestEpochToPredict, owner.address, userAuth); expect(prediction.predictedValue).to.be.eq(!predictedValue); + await mockErc20.approve(erc20Token.address, 1); let mockErc20BalanceBefore = await mockErc20.balanceOf(owner.address); await erc20Token.submitPredval(predictedValue, stake + 1, soonestEpochToPredict); let mockErc20BalanceAfter = await mockErc20.balanceOf(owner.address); From a8a2fd5826e6fc3c3aee55c5c0275bfe638f0cab Mon Sep 17 00:00:00 2001 From: trizin <25263018+trizin@users.noreply.github.com> Date: Sat, 5 Aug 2023 18:24:37 +0300 Subject: [PATCH 18/30] Fix test --- test/unit/datatokens/ERC20Template3.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/unit/datatokens/ERC20Template3.test.js b/test/unit/datatokens/ERC20Template3.test.js index efdbbe02..92e8b469 100644 --- a/test/unit/datatokens/ERC20Template3.test.js +++ b/test/unit/datatokens/ERC20Template3.test.js @@ -1209,7 +1209,7 @@ describe("ERC20Template3", () => { const secondsPerEpoch = await erc20Token.secondsPerEpoch(); fastForward(secondsPerEpoch) curEpoch = await erc20Token.curEpoch(); - const [numer2, denom2] = await erc20Token.connect(user2).getAggPredval(soonestEpochToPredict, userAuth); + const [numer2, denom2] = await erc20Token.connect(user2).getAggPredval(curEpoch, userAuth); expect(numer2).to.be.eq(web3.utils.toWei("1")); expect(denom2).to.be.eq(web3.utils.toWei("1")); From b56297bc4c699b9e5ab2bb65de9b2cb5a76dd2f1 Mon Sep 17 00:00:00 2001 From: trizin <25263018+trizin@users.noreply.github.com> Date: Sat, 5 Aug 2023 18:34:07 +0300 Subject: [PATCH 19/30] Fix transfer --- contracts/templates/ERC20Template3.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/templates/ERC20Template3.sol b/contracts/templates/ERC20Template3.sol index f34f8a4c..62073bc7 100644 --- a/contracts/templates/ERC20Template3.sol +++ b/contracts/templates/ERC20Template3.sol @@ -1013,7 +1013,7 @@ contract ERC20Template3 is IERC20(stakeToken).safeTransferFrom(msg.sender, address(this), payment); } else if (stake < oldStake) { uint256 refund = oldStake - stake; - IERC20(stakeToken).safeTransferFrom(address(this), msg.sender, refund); + IERC20(stakeToken).transfer(msg.sender, refund); } predictions[epoch_start][msg.sender].predictedValue = predictedValue; predictions[epoch_start][msg.sender].stake = stake; From bfeaad10168bc44d8c24e4787e3f33b54106fba5 Mon Sep 17 00:00:00 2001 From: trizin <25263018+trizin@users.noreply.github.com> Date: Sat, 5 Aug 2023 18:34:13 +0300 Subject: [PATCH 20/30] Fix epoch ts --- test/unit/datatokens/ERC20Template3.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/unit/datatokens/ERC20Template3.test.js b/test/unit/datatokens/ERC20Template3.test.js index 92e8b469..341e83c9 100644 --- a/test/unit/datatokens/ERC20Template3.test.js +++ b/test/unit/datatokens/ERC20Template3.test.js @@ -1209,7 +1209,7 @@ describe("ERC20Template3", () => { const secondsPerEpoch = await erc20Token.secondsPerEpoch(); fastForward(secondsPerEpoch) curEpoch = await erc20Token.curEpoch(); - const [numer2, denom2] = await erc20Token.connect(user2).getAggPredval(curEpoch, userAuth); + const [numer2, denom2] = await erc20Token.connect(user2).getAggPredval(curEpoch + secondsPerEpoch, userAuth); expect(numer2).to.be.eq(web3.utils.toWei("1")); expect(denom2).to.be.eq(web3.utils.toWei("1")); From 82466d21218719cfb96d2d89afa4aba5a65c7694 Mon Sep 17 00:00:00 2001 From: trizin <25263018+trizin@users.noreply.github.com> Date: Sat, 5 Aug 2023 19:54:27 +0300 Subject: [PATCH 21/30] Fix test --- test/unit/datatokens/ERC20Template3.test.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/unit/datatokens/ERC20Template3.test.js b/test/unit/datatokens/ERC20Template3.test.js index 341e83c9..188c25c4 100644 --- a/test/unit/datatokens/ERC20Template3.test.js +++ b/test/unit/datatokens/ERC20Template3.test.js @@ -849,12 +849,12 @@ describe("ERC20Template3", () => { let mockErc20BalanceBefore = await mockErc20.balanceOf(owner.address); await erc20Token.submitPredval(predictedValue, stake + 1, soonestEpochToPredict); let mockErc20BalanceAfter = await mockErc20.balanceOf(owner.address); - expect(mockErc20BalanceAfter).to.equal(mockErc20BalanceBefore.add(-1)) + expect(mockErc20BalanceBefore).to.equal(mockErc20BalanceAfter.add(1)) mockErc20BalanceBefore = await mockErc20.balanceOf(owner.address); await erc20Token.submitPredval(predictedValue, stake - 1, soonestEpochToPredict), mockErc20BalanceAfter = await mockErc20.balanceOf(owner.address); - expect(mockErc20BalanceAfter).to.equal(mockErc20BalanceBefore.add(1)) + expect(mockErc20BalanceAfter).to.equal(mockErc20BalanceBefore.add(2)) }); it("#pausePredictions - should pause and resume predictions", async () => { await erc20Token.pausePredictions(); From a13cc1574753e3bd40d260ff86b54cff1c22c944 Mon Sep 17 00:00:00 2001 From: trizin <25263018+trizin@users.noreply.github.com> Date: Sat, 5 Aug 2023 19:54:55 +0300 Subject: [PATCH 22/30] await fastforward command --- test/unit/datatokens/ERC20Template3.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/unit/datatokens/ERC20Template3.test.js b/test/unit/datatokens/ERC20Template3.test.js index 188c25c4..8597148e 100644 --- a/test/unit/datatokens/ERC20Template3.test.js +++ b/test/unit/datatokens/ERC20Template3.test.js @@ -1207,7 +1207,7 @@ describe("ERC20Template3", () => { await erc20Token.connect(user3).submitPredval(predictedValue, stake, soonestEpochToPredict); const secondsPerEpoch = await erc20Token.secondsPerEpoch(); - fastForward(secondsPerEpoch) + await fastForward(secondsPerEpoch) curEpoch = await erc20Token.curEpoch(); const [numer2, denom2] = await erc20Token.connect(user2).getAggPredval(curEpoch + secondsPerEpoch, userAuth); expect(numer2).to.be.eq(web3.utils.toWei("1")); From cb5f72a153d8cadb8bea94446116c7c32d3caf6d Mon Sep 17 00:00:00 2001 From: trizin <25263018+trizin@users.noreply.github.com> Date: Sat, 5 Aug 2023 19:56:11 +0300 Subject: [PATCH 23/30] Add tests for total stake function --- test/unit/datatokens/ERC20Template3.test.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/unit/datatokens/ERC20Template3.test.js b/test/unit/datatokens/ERC20Template3.test.js index 8597148e..32268a6b 100644 --- a/test/unit/datatokens/ERC20Template3.test.js +++ b/test/unit/datatokens/ERC20Template3.test.js @@ -1193,11 +1193,14 @@ describe("ERC20Template3", () => { let soonestEpochToPredict = await erc20Token.soonestEpochToPredict(await blocktimestamp()); const userAuth = await authorize(user2.address) await expectRevert(erc20Token.connect(user2).getAggPredval(soonestEpochToPredict, userAuth), "predictions not closed"); + await expectRevert(erc20Token.getTotalStake(soonestEpochToPredict), "predictions not closed"); let curEpoch = await erc20Token.curEpoch(); const [numer, denom] = await erc20Token.connect(user2).getAggPredval(curEpoch, userAuth); + const totalStake = await erc20Token.getTotalStake(curEpoch); expect(numer).to.be.eq(0); expect(denom).to.be.eq(0); + expect(totalStake).to.be.eq(0); // user2 makes a prediction const predictedValue = true; @@ -1210,8 +1213,10 @@ describe("ERC20Template3", () => { await fastForward(secondsPerEpoch) curEpoch = await erc20Token.curEpoch(); const [numer2, denom2] = await erc20Token.connect(user2).getAggPredval(curEpoch + secondsPerEpoch, userAuth); + const totalStake2 = await erc20Token.getTotalStake(curEpoch); expect(numer2).to.be.eq(web3.utils.toWei("1")); expect(denom2).to.be.eq(web3.utils.toWei("1")); + expect(totalStake2).to.be.eq(web3.utils.toWei("1")); // check subscription revenue const revenue = await erc20Token.getsubscriptionRevenueAtEpoch(soonestEpochToPredict); From d30cc1f9d48c2f17949d485b43fdd1a65ad4d9ce Mon Sep 17 00:00:00 2001 From: trizin <25263018+trizin@users.noreply.github.com> Date: Sat, 5 Aug 2023 20:57:23 +0300 Subject: [PATCH 24/30] Fix type error --- test/unit/datatokens/ERC20Template3.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/unit/datatokens/ERC20Template3.test.js b/test/unit/datatokens/ERC20Template3.test.js index 32268a6b..a298fd77 100644 --- a/test/unit/datatokens/ERC20Template3.test.js +++ b/test/unit/datatokens/ERC20Template3.test.js @@ -1210,7 +1210,7 @@ describe("ERC20Template3", () => { await erc20Token.connect(user3).submitPredval(predictedValue, stake, soonestEpochToPredict); const secondsPerEpoch = await erc20Token.secondsPerEpoch(); - await fastForward(secondsPerEpoch) + await fastForward(secondsPerEpoch.toNumber()) curEpoch = await erc20Token.curEpoch(); const [numer2, denom2] = await erc20Token.connect(user2).getAggPredval(curEpoch + secondsPerEpoch, userAuth); const totalStake2 = await erc20Token.getTotalStake(curEpoch); From 54b4d301b8f4c3d5bfbb1f021b6e153d5b4a5c70 Mon Sep 17 00:00:00 2001 From: trizin <25263018+trizin@users.noreply.github.com> Date: Sat, 5 Aug 2023 18:25:55 +0000 Subject: [PATCH 25/30] Set seconds per epoch to 300 --- test/unit/datatokens/ERC20Template3.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/unit/datatokens/ERC20Template3.test.js b/test/unit/datatokens/ERC20Template3.test.js index a298fd77..6111ac23 100644 --- a/test/unit/datatokens/ERC20Template3.test.js +++ b/test/unit/datatokens/ERC20Template3.test.js @@ -23,7 +23,7 @@ const fastForward = async (seconds) => { await ethers.provider.send("evm_mine"); } -const sPerEpoch = 288; +const sPerEpoch = 300; const sPerSubscription = 24 * 60 * 60; const trueValueSubmitTimeout = 24 * 60 * 60 * 3; From e93a3684a60aea15cd3e69eb8222ec158e2bb175 Mon Sep 17 00:00:00 2001 From: trizin <25263018+trizin@users.noreply.github.com> Date: Sat, 5 Aug 2023 18:35:39 +0000 Subject: [PATCH 26/30] Add a test for toEpochStart --- test/unit/datatokens/ERC20Template3.test.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/test/unit/datatokens/ERC20Template3.test.js b/test/unit/datatokens/ERC20Template3.test.js index 6111ac23..4b39a862 100644 --- a/test/unit/datatokens/ERC20Template3.test.js +++ b/test/unit/datatokens/ERC20Template3.test.js @@ -700,6 +700,13 @@ describe("ERC20Template3", () => { }); // PREDICTOOR + it("#toEpochStart - Should return the start of the epoch for a given timestamp", async function() { + const testTimestamp = 1691374249 + const secondsPerEpoch = await erc20Token.secondsPerEpoch() + const expectedEpochStart = Math.floor(testTimestamp / secondsPerEpoch) * secondsPerEpoch; + const result = await erc20Token.toEpochStart(testTimestamp); + expect(result.toNumber()).to.equal(expectedEpochStart); + }); it("#secondsPerEpoch - secondsPerEpoch should be set", async () => { const secondsPerEpoch = await erc20Token.secondsPerEpoch(); assert(secondsPerEpoch > 0, 'Invalid secondsPerEpoch'); From 720bc34db1c8ac0da6c7eb4618bad762f0af2418 Mon Sep 17 00:00:00 2001 From: trizin <25263018+trizin@users.noreply.github.com> Date: Sat, 5 Aug 2023 18:38:31 +0000 Subject: [PATCH 27/30] Fix testes where hardcoded values are used --- test/unit/datatokens/ERC20Template3.test.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/test/unit/datatokens/ERC20Template3.test.js b/test/unit/datatokens/ERC20Template3.test.js index 4b39a862..ed8b4f93 100644 --- a/test/unit/datatokens/ERC20Template3.test.js +++ b/test/unit/datatokens/ERC20Template3.test.js @@ -1349,7 +1349,9 @@ describe("ERC20Template3", () => { const balAfter = await mockErc20.balanceOf(user3.address); expect(balAfter).to.be.gt(balBefore); const profit = balAfter.sub(balBefore); - const expectedProfit = 1 + (2 / parseInt(3600 / parseInt(300 / 24))) + const secondsPerEpoch = await erc20Token.secondsPerEpoch(); + const secondsPerSubscription = await erc20Token.secondsPerSubscription(); + const expectedProfit = 1 + (2 / secondsPerSubscription * secondsPerEpoch) expect(parseFloat(web3.utils.fromWei(profit.toString()))).to.be.eq(expectedProfit); // user tries to call payout for the same slot @@ -1478,7 +1480,9 @@ describe("ERC20Template3", () => { expect(balAfter).to.be.gt(balBefore); const profit = balAfter.sub(balBefore); - const expectedProfit = 1 + (2 / parseInt(3600 / parseInt(300 / 24))) + const secondsPerEpoch = await erc20Token.secondsPerEpoch(); + const secondsPerSubscription = await erc20Token.secondsPerSubscription(); + const expectedProfit = 1 + (2 / secondsPerSubscription * secondsPerEpoch); expect(parseFloat(web3.utils.fromWei(profit.toString()))).to.be.eq(expectedProfit); mockErc20Balance = await mockErc20.balanceOf(user3.address) @@ -1634,7 +1638,7 @@ describe("ERC20Template3", () => { let event_2 = getEventFromTx(txReceipt_2, 'Transfer') expect(event_2.args.from).to.be.eq(erc20Token.address); expect(event_2.args.to).to.be.eq(freMarketFeeCollector.address); - expect(event_2.args.value).to.be.eq(6666666666666666); + expect(event_2.args.value).to.be.eq(revenue_at_block); }) it("#redeemUnusedSlotRevenue - admin should not be able to redeem for future epoch", async () => { const secondsPerEpoch = await erc20Token.secondsPerEpoch(); From 5e757974a880668de4a8141d029a7e4c043acbd9 Mon Sep 17 00:00:00 2001 From: trizin <25263018+trizin@users.noreply.github.com> Date: Sat, 5 Aug 2023 18:48:31 +0000 Subject: [PATCH 28/30] Require s_per_subscription % s_per_epoch == 0 --- contracts/templates/ERC20Template3.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/templates/ERC20Template3.sol b/contracts/templates/ERC20Template3.sol index 62073bc7..fbc5b598 100644 --- a/contracts/templates/ERC20Template3.sol +++ b/contracts/templates/ERC20Template3.sol @@ -15,7 +15,6 @@ import "@openzeppelin/contracts/utils/math/SafeMath.sol"; import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import "@openzeppelin/contracts/security/ReentrancyGuard.sol"; import "../utils/ERC20Roles.sol"; - /** * @title DatatokenTemplate * @@ -1181,6 +1180,7 @@ contract ERC20Template3 is uint256 s_per_subscription, uint256 _truval_submit_timeout ) internal { + require(s_per_subscription % s_per_epoch == 0, "%"); if (secondsPerEpoch == 0) { secondsPerEpoch = s_per_epoch; } From e7afa9f5987d7db3d7ad5ebe6a4f639946c11f62 Mon Sep 17 00:00:00 2001 From: trizin <25263018+trizin@users.noreply.github.com> Date: Sat, 5 Aug 2023 18:48:43 +0000 Subject: [PATCH 29/30] Fix test --- test/unit/datatokens/ERC20Template3.test.js | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/test/unit/datatokens/ERC20Template3.test.js b/test/unit/datatokens/ERC20Template3.test.js index ed8b4f93..e60eb17d 100644 --- a/test/unit/datatokens/ERC20Template3.test.js +++ b/test/unit/datatokens/ERC20Template3.test.js @@ -1203,8 +1203,10 @@ describe("ERC20Template3", () => { await expectRevert(erc20Token.getTotalStake(soonestEpochToPredict), "predictions not closed"); let curEpoch = await erc20Token.curEpoch(); - const [numer, denom] = await erc20Token.connect(user2).getAggPredval(curEpoch, userAuth); - const totalStake = await erc20Token.getTotalStake(curEpoch); + const secondsPerEpoch = await erc20Token.secondsPerEpoch(); + let predictedEpoch = curEpoch.add(secondsPerEpoch); + const [numer, denom] = await erc20Token.connect(user2).getAggPredval(predictedEpoch, userAuth); + const totalStake = await erc20Token.getTotalStake(predictedEpoch); expect(numer).to.be.eq(0); expect(denom).to.be.eq(0); expect(totalStake).to.be.eq(0); @@ -1216,11 +1218,11 @@ describe("ERC20Template3", () => { await mockErc20.connect(user3).approve(erc20Token.address, stake); await erc20Token.connect(user3).submitPredval(predictedValue, stake, soonestEpochToPredict); - const secondsPerEpoch = await erc20Token.secondsPerEpoch(); await fastForward(secondsPerEpoch.toNumber()) curEpoch = await erc20Token.curEpoch(); - const [numer2, denom2] = await erc20Token.connect(user2).getAggPredval(curEpoch + secondsPerEpoch, userAuth); - const totalStake2 = await erc20Token.getTotalStake(curEpoch); + predictedEpoch = curEpoch.add(secondsPerEpoch); + const [numer2, denom2] = await erc20Token.connect(user2).getAggPredval(predictedEpoch, userAuth); + const totalStake2 = await erc20Token.getTotalStake(predictedEpoch); expect(numer2).to.be.eq(web3.utils.toWei("1")); expect(denom2).to.be.eq(web3.utils.toWei("1")); expect(totalStake2).to.be.eq(web3.utils.toWei("1")); From 5ba4ff6764d30fd9656b6a823d13a34e74fbe2f6 Mon Sep 17 00:00:00 2001 From: trizin <25263018+trizin@users.noreply.github.com> Date: Sat, 5 Aug 2023 22:05:28 +0300 Subject: [PATCH 30/30] Reentrancy precaution --- contracts/templates/ERC20Template3.sol | 1 + 1 file changed, 1 insertion(+) diff --git a/contracts/templates/ERC20Template3.sol b/contracts/templates/ERC20Template3.sol index fbc5b598..9c2f413d 100644 --- a/contracts/templates/ERC20Template3.sol +++ b/contracts/templates/ERC20Template3.sol @@ -1007,6 +1007,7 @@ contract ERC20Template3 is emit PredictionSubmitted(msg.sender, epoch_start, stake); if (submittedPredval(epoch_start, msg.sender)) { uint256 oldStake = predictions[epoch_start][msg.sender].stake; + predictions[epoch_start][msg.sender].stake = 0; // Reentrancy precaution if (stake > oldStake) { uint256 payment = stake - oldStake; IERC20(stakeToken).safeTransferFrom(msg.sender, address(this), payment);