From 9b32ef29e993a215b0507a85b48311602f959c29 Mon Sep 17 00:00:00 2001 From: udkreddySomish Date: Sat, 17 Oct 2020 22:52:20 +0530 Subject: [PATCH 01/58] Distribute rewards based on gas price and bonus bPLOT --- contracts/MarketRegistry.sol | 55 ++++++++++++++++++++++++- contracts/interfaces/IMarketUtility.sol | 11 +++++ 2 files changed, 65 insertions(+), 1 deletion(-) diff --git a/contracts/MarketRegistry.sol b/contracts/MarketRegistry.sol index e6c36f80..dee6e123 100644 --- a/contracts/MarketRegistry.sol +++ b/contracts/MarketRegistry.sol @@ -72,7 +72,7 @@ contract MarketRegistry is Governed, Iupgradable { } uint internal marketCreationIncentive; - + mapping(address => MarketData) marketData; mapping(address => UserData) userData; mapping(uint256 => mapping(uint256 => MarketCreationData)) public marketCreationData; @@ -92,6 +92,16 @@ contract MarketRegistry is Governed, Iupgradable { IGovernance internal governance; IMaster ms; + uint internal bPlotIncentive; + uint internal timeForMaxBonus; + IToken internal bPLOTToken; + + struct MarketCreationIncentiveData { + uint256 plotIncentive; + uint256 bPlotIncentive; + } + + mapping(address => MarketCreationIncentiveData) userIncentives; event MarketQuestion(address indexed marketAdd, bytes32 stockName, uint256 indexed predictionType, uint256 startTime); event PlacePrediction(address indexed user,uint256 value, uint256 predictionPoints, address predictionAsset,uint256 prediction,address indexed marketAdd,uint256 _leverage); @@ -101,6 +111,7 @@ contract MarketRegistry is Governed, Iupgradable { event MarketCurrencies(uint256 indexed index, address marketImplementation, address feedAddress, bytes32 currencyName); event DisputeRaised(address indexed marketAdd, address raisedBy, uint64 proposalId, uint256 proposedValue); event DisputeResolved(address indexed marketAdd, bool status); + event MarketCreationReward(address indexed createdBy, uint256 createdAfter, uint256 plotIncentive, uint256 bPlotIncentive, uint256 gasUsed, uint256 gasCost); /** * @dev Checks if given addres is valid market address. @@ -130,6 +141,17 @@ contract MarketRegistry is Governed, Iupgradable { marketInitiater = _defaultAddress; } + /** + * @dev Set initial market creation incentive params. + */ + function setInitialCreationIncentives() public { + require(address(ms) == msg.sender); + timeForMaxBonus = 5 minutes; + bPlotIncentive = 50 ether; + address bPLOTAddress = ms.getLatestAddress("BL"); + bPLOTToken = IToken(bPLOTAddress); + } + /** * @dev Start the initial market. */ @@ -256,6 +278,7 @@ contract MarketRegistry is Governed, Iupgradable { * @param _marketCurrencyIndex the index of market currency. */ function createMarket(uint256 _marketType, uint256 _marketCurrencyIndex) public payable{ + uint256 gasProvided = gasleft(); address penultimateMarket = marketCreationData[_marketType][_marketCurrencyIndex].penultimateMarket; if(penultimateMarket != address(0)) { IMarket(penultimateMarket).settleMarket(); @@ -275,6 +298,22 @@ contract MarketRegistry is Governed, Iupgradable { uint64 _maxValue = uint64((ceil(currentPrice.add(_optionRangePerc).div(_roundOfToNearest), 10**_decimals)).mul(_roundOfToNearest)); _createMarket(_marketType, _marketCurrencyIndex, _minValue, _maxValue, _marketStartTime, _currencyName); userData[msg.sender].marketsCreated++; + uint256 gasUsed = gasleft(); + _calculateIncentive(gasUsed, _marketStartTime); + } + + function _calculateIncentive(uint256 gasUsed, uint256 _marketStartTime) internal{ + uint256 gasCost = gasUsed * tx.gasprice * 10**9; + uint256 incentive = marketUtility.getAssetValueETH(address(plotToken), gasCost); + uint256 bPlotBonus; + uint256 createdAfter = now - _marketStartTime; + if(createdAfter <= timeForMaxBonus) { + bPlotBonus = bPlotIncentive; + } else { + bPlotBonus = bPlotIncentive.div(2); + } + userIncentives[msg.sender] = MarketCreationIncentiveData(incentive, bPlotBonus); + emit MarketCreationReward(msg.sender, createdAfter, incentive, bPlotBonus, gasUsed, gasCost); } /** @@ -286,6 +325,10 @@ contract MarketRegistry is Governed, Iupgradable { require(plotToken.balanceOf(address(this)) > pendingReward); delete userData[msg.sender].marketsCreated; _transferAsset(address(plotToken), msg.sender, pendingReward); + + require(userIncentives[msg.sender].plotIncentive > 0); + _transferAsset(address(plotToken), msg.sender, userIncentives[msg.sender].plotIncentive); + _transferAsset(address(bPLOTToken), msg.sender, userIncentives[msg.sender].bPlotIncentive); } function calculateStartTimeForMarket(uint256 _marketType, uint256 _marketCurrencyIndex) public view returns(uint64 _marketStartTime) { @@ -419,6 +462,10 @@ contract MarketRegistry is Governed, Iupgradable { function updateUintParameters(bytes8 code, uint256 value) external onlyAuthorizedToGovern { if(code == "MCRINC") { // Incentive to be distributed to user for market creation marketCreationIncentive = value; + } else if(code == "BPLOTINC") { // bPLOT Incentive to be distributed to user for market creation + bPlotIncentive = value; + } else if(code == "MAXBTIME") { // Time before which if market is created, user granted maximum bPLOT bonus + timeForMaxBonus = value; } else { marketUtility.updateUintParameters(code, value); } @@ -491,6 +538,12 @@ contract MarketRegistry is Governed, Iupgradable { if(code == "MCRINC") { codeVal = code; value = marketCreationIncentive; + } else if(code == "BPLOTINC") { + codeVal = code; + value = bPlotIncentive; + } else if(code == "MAXBTIME") { + codeVal = code; + value = timeForMaxBonus; } } diff --git a/contracts/interfaces/IMarketUtility.sol b/contracts/interfaces/IMarketUtility.sol index 9f2e7619..0c5fd781 100644 --- a/contracts/interfaces/IMarketUtility.sol +++ b/contracts/interfaces/IMarketUtility.sol @@ -69,4 +69,15 @@ contract IMarketUtility { address _currencyFeedAddress, uint256 _settleTime ) public view returns (uint256 latestAnswer, uint256 roundId); + + /** + * @dev Get value of provided currency address in ETH + * @param _currencyAddress Address of currency + * @param _amount Amount of provided currency + * @return Value of provided amount in ETH + **/ + function getAssetValueETH(address _currencyAddress, uint256 _amount) + public + view + returns (uint256 tokenEthValue); } From 2e5ceefe3edfe0f61e9364e2d74714a147c946cf Mon Sep 17 00:00:00 2001 From: udkreddySomish Date: Sat, 17 Oct 2020 22:54:39 +0530 Subject: [PATCH 02/58] Restrict setting initial creation incentives multiple times --- contracts/MarketRegistry.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/MarketRegistry.sol b/contracts/MarketRegistry.sol index dee6e123..6bc7a751 100644 --- a/contracts/MarketRegistry.sol +++ b/contracts/MarketRegistry.sol @@ -145,7 +145,7 @@ contract MarketRegistry is Governed, Iupgradable { * @dev Set initial market creation incentive params. */ function setInitialCreationIncentives() public { - require(address(ms) == msg.sender); + require(address(bPLOTToken) == address(0)); timeForMaxBonus = 5 minutes; bPlotIncentive = 50 ether; address bPLOTAddress = ms.getLatestAddress("BL"); From ba9a4aab6139ff141b1b49c7b154058d51ae2412 Mon Sep 17 00:00:00 2001 From: udkreddySomish Date: Sun, 18 Oct 2020 19:51:57 +0530 Subject: [PATCH 03/58] Handle rewards of market creators before the contract was upgraded --- contracts/MarketRegistry.sol | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/contracts/MarketRegistry.sol b/contracts/MarketRegistry.sol index 6bc7a751..e2ffc46a 100644 --- a/contracts/MarketRegistry.sol +++ b/contracts/MarketRegistry.sol @@ -297,7 +297,7 @@ contract MarketRegistry is Governed, Iupgradable { uint64 _minValue = uint64((ceil(currentPrice.sub(_optionRangePerc).div(_roundOfToNearest), 10**_decimals)).mul(_roundOfToNearest)); uint64 _maxValue = uint64((ceil(currentPrice.add(_optionRangePerc).div(_roundOfToNearest), 10**_decimals)).mul(_roundOfToNearest)); _createMarket(_marketType, _marketCurrencyIndex, _minValue, _maxValue, _marketStartTime, _currencyName); - userData[msg.sender].marketsCreated++; + // userData[msg.sender].marketsCreated++; uint256 gasUsed = gasleft(); _calculateIncentive(gasUsed, _marketStartTime); } @@ -320,14 +320,16 @@ contract MarketRegistry is Governed, Iupgradable { * @dev function to reward user for initiating market creation calls */ function claimCreationReward() external { - require(userData[msg.sender].marketsCreated > 0); - uint256 pendingReward = marketCreationIncentive.mul(userData[msg.sender].marketsCreated); - require(plotToken.balanceOf(address(this)) > pendingReward); - delete userData[msg.sender].marketsCreated; - _transferAsset(address(plotToken), msg.sender, pendingReward); - - require(userIncentives[msg.sender].plotIncentive > 0); - _transferAsset(address(plotToken), msg.sender, userIncentives[msg.sender].plotIncentive); + uint256 pendingPLOTReward; + if(userData[msg.sender].marketsCreated > 0) { + pendingPLOTReward = marketCreationIncentive.mul(userData[msg.sender].marketsCreated); + delete userData[msg.sender].marketsCreated; + } + pendingPLOTReward = pendingPLOTReward.add(userIncentives[msg.sender].plotIncentive); + require(pendingPLOTReward > 0); + require(plotToken.balanceOf(address(this)) > pendingPLOTReward); + + _transferAsset(address(plotToken), msg.sender, pendingPLOTReward); _transferAsset(address(bPLOTToken), msg.sender, userIncentives[msg.sender].bPlotIncentive); } From b749437fe0b9cea0a62cff800439d13a902b6984 Mon Sep 17 00:00:00 2001 From: udkreddySomish Date: Mon, 19 Oct 2020 11:00:38 +0530 Subject: [PATCH 04/58] corrected gas used variable --- contracts/MarketRegistry.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/MarketRegistry.sol b/contracts/MarketRegistry.sol index e2ffc46a..2c59d865 100644 --- a/contracts/MarketRegistry.sol +++ b/contracts/MarketRegistry.sol @@ -298,7 +298,7 @@ contract MarketRegistry is Governed, Iupgradable { uint64 _maxValue = uint64((ceil(currentPrice.add(_optionRangePerc).div(_roundOfToNearest), 10**_decimals)).mul(_roundOfToNearest)); _createMarket(_marketType, _marketCurrencyIndex, _minValue, _maxValue, _marketStartTime, _currencyName); // userData[msg.sender].marketsCreated++; - uint256 gasUsed = gasleft(); + uint256 gasUsed = gasleft() - gasProvided; _calculateIncentive(gasUsed, _marketStartTime); } From 1cb74a09c80e12cd4a4e4b1c075891f888228a1c Mon Sep 17 00:00:00 2001 From: udkreddySomish Date: Mon, 19 Oct 2020 11:21:51 +0530 Subject: [PATCH 05/58] Added buffer gas for incentive calculation --- contracts/MarketRegistry.sol | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/contracts/MarketRegistry.sol b/contracts/MarketRegistry.sol index 2c59d865..16094d43 100644 --- a/contracts/MarketRegistry.sol +++ b/contracts/MarketRegistry.sol @@ -298,11 +298,13 @@ contract MarketRegistry is Governed, Iupgradable { uint64 _maxValue = uint64((ceil(currentPrice.add(_optionRangePerc).div(_roundOfToNearest), 10**_decimals)).mul(_roundOfToNearest)); _createMarket(_marketType, _marketCurrencyIndex, _minValue, _maxValue, _marketStartTime, _currencyName); // userData[msg.sender].marketsCreated++; - uint256 gasUsed = gasleft() - gasProvided; + uint256 gasUsed = gasProvided - gasleft(); _calculateIncentive(gasUsed, _marketStartTime); } function _calculateIncentive(uint256 gasUsed, uint256 _marketStartTime) internal{ + //Adding buffer gas for below calculations + gasUsed = gasUsed + 32000; uint256 gasCost = gasUsed * tx.gasprice * 10**9; uint256 incentive = marketUtility.getAssetValueETH(address(plotToken), gasCost); uint256 bPlotBonus; From e5379b7fbd3e5c4d8d8c9ede029414a765b4807e Mon Sep 17 00:00:00 2001 From: udkreddySomish Date: Mon, 19 Oct 2020 17:14:44 +0530 Subject: [PATCH 06/58] Added new contract for new creation incentive calculation --- contracts/MarketRegistry.sol | 71 ++--------------- contracts/MarketRegistryNew.sol | 132 ++++++++++++++++++++++++++++++++ 2 files changed, 139 insertions(+), 64 deletions(-) create mode 100644 contracts/MarketRegistryNew.sol diff --git a/contracts/MarketRegistry.sol b/contracts/MarketRegistry.sol index 16094d43..e6c36f80 100644 --- a/contracts/MarketRegistry.sol +++ b/contracts/MarketRegistry.sol @@ -72,7 +72,7 @@ contract MarketRegistry is Governed, Iupgradable { } uint internal marketCreationIncentive; - + mapping(address => MarketData) marketData; mapping(address => UserData) userData; mapping(uint256 => mapping(uint256 => MarketCreationData)) public marketCreationData; @@ -92,16 +92,6 @@ contract MarketRegistry is Governed, Iupgradable { IGovernance internal governance; IMaster ms; - uint internal bPlotIncentive; - uint internal timeForMaxBonus; - IToken internal bPLOTToken; - - struct MarketCreationIncentiveData { - uint256 plotIncentive; - uint256 bPlotIncentive; - } - - mapping(address => MarketCreationIncentiveData) userIncentives; event MarketQuestion(address indexed marketAdd, bytes32 stockName, uint256 indexed predictionType, uint256 startTime); event PlacePrediction(address indexed user,uint256 value, uint256 predictionPoints, address predictionAsset,uint256 prediction,address indexed marketAdd,uint256 _leverage); @@ -111,7 +101,6 @@ contract MarketRegistry is Governed, Iupgradable { event MarketCurrencies(uint256 indexed index, address marketImplementation, address feedAddress, bytes32 currencyName); event DisputeRaised(address indexed marketAdd, address raisedBy, uint64 proposalId, uint256 proposedValue); event DisputeResolved(address indexed marketAdd, bool status); - event MarketCreationReward(address indexed createdBy, uint256 createdAfter, uint256 plotIncentive, uint256 bPlotIncentive, uint256 gasUsed, uint256 gasCost); /** * @dev Checks if given addres is valid market address. @@ -141,17 +130,6 @@ contract MarketRegistry is Governed, Iupgradable { marketInitiater = _defaultAddress; } - /** - * @dev Set initial market creation incentive params. - */ - function setInitialCreationIncentives() public { - require(address(bPLOTToken) == address(0)); - timeForMaxBonus = 5 minutes; - bPlotIncentive = 50 ether; - address bPLOTAddress = ms.getLatestAddress("BL"); - bPLOTToken = IToken(bPLOTAddress); - } - /** * @dev Start the initial market. */ @@ -278,7 +256,6 @@ contract MarketRegistry is Governed, Iupgradable { * @param _marketCurrencyIndex the index of market currency. */ function createMarket(uint256 _marketType, uint256 _marketCurrencyIndex) public payable{ - uint256 gasProvided = gasleft(); address penultimateMarket = marketCreationData[_marketType][_marketCurrencyIndex].penultimateMarket; if(penultimateMarket != address(0)) { IMarket(penultimateMarket).settleMarket(); @@ -297,42 +274,18 @@ contract MarketRegistry is Governed, Iupgradable { uint64 _minValue = uint64((ceil(currentPrice.sub(_optionRangePerc).div(_roundOfToNearest), 10**_decimals)).mul(_roundOfToNearest)); uint64 _maxValue = uint64((ceil(currentPrice.add(_optionRangePerc).div(_roundOfToNearest), 10**_decimals)).mul(_roundOfToNearest)); _createMarket(_marketType, _marketCurrencyIndex, _minValue, _maxValue, _marketStartTime, _currencyName); - // userData[msg.sender].marketsCreated++; - uint256 gasUsed = gasProvided - gasleft(); - _calculateIncentive(gasUsed, _marketStartTime); - } - - function _calculateIncentive(uint256 gasUsed, uint256 _marketStartTime) internal{ - //Adding buffer gas for below calculations - gasUsed = gasUsed + 32000; - uint256 gasCost = gasUsed * tx.gasprice * 10**9; - uint256 incentive = marketUtility.getAssetValueETH(address(plotToken), gasCost); - uint256 bPlotBonus; - uint256 createdAfter = now - _marketStartTime; - if(createdAfter <= timeForMaxBonus) { - bPlotBonus = bPlotIncentive; - } else { - bPlotBonus = bPlotIncentive.div(2); - } - userIncentives[msg.sender] = MarketCreationIncentiveData(incentive, bPlotBonus); - emit MarketCreationReward(msg.sender, createdAfter, incentive, bPlotBonus, gasUsed, gasCost); + userData[msg.sender].marketsCreated++; } /** * @dev function to reward user for initiating market creation calls */ function claimCreationReward() external { - uint256 pendingPLOTReward; - if(userData[msg.sender].marketsCreated > 0) { - pendingPLOTReward = marketCreationIncentive.mul(userData[msg.sender].marketsCreated); - delete userData[msg.sender].marketsCreated; - } - pendingPLOTReward = pendingPLOTReward.add(userIncentives[msg.sender].plotIncentive); - require(pendingPLOTReward > 0); - require(plotToken.balanceOf(address(this)) > pendingPLOTReward); - - _transferAsset(address(plotToken), msg.sender, pendingPLOTReward); - _transferAsset(address(bPLOTToken), msg.sender, userIncentives[msg.sender].bPlotIncentive); + require(userData[msg.sender].marketsCreated > 0); + uint256 pendingReward = marketCreationIncentive.mul(userData[msg.sender].marketsCreated); + require(plotToken.balanceOf(address(this)) > pendingReward); + delete userData[msg.sender].marketsCreated; + _transferAsset(address(plotToken), msg.sender, pendingReward); } function calculateStartTimeForMarket(uint256 _marketType, uint256 _marketCurrencyIndex) public view returns(uint64 _marketStartTime) { @@ -466,10 +419,6 @@ contract MarketRegistry is Governed, Iupgradable { function updateUintParameters(bytes8 code, uint256 value) external onlyAuthorizedToGovern { if(code == "MCRINC") { // Incentive to be distributed to user for market creation marketCreationIncentive = value; - } else if(code == "BPLOTINC") { // bPLOT Incentive to be distributed to user for market creation - bPlotIncentive = value; - } else if(code == "MAXBTIME") { // Time before which if market is created, user granted maximum bPLOT bonus - timeForMaxBonus = value; } else { marketUtility.updateUintParameters(code, value); } @@ -542,12 +491,6 @@ contract MarketRegistry is Governed, Iupgradable { if(code == "MCRINC") { codeVal = code; value = marketCreationIncentive; - } else if(code == "BPLOTINC") { - codeVal = code; - value = bPlotIncentive; - } else if(code == "MAXBTIME") { - codeVal = code; - value = timeForMaxBonus; } } diff --git a/contracts/MarketRegistryNew.sol b/contracts/MarketRegistryNew.sol new file mode 100644 index 00000000..ecb9335e --- /dev/null +++ b/contracts/MarketRegistryNew.sol @@ -0,0 +1,132 @@ +/* Copyright (C) 2020 PlotX.io + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see http://www.gnu.org/licenses/ */ + +pragma solidity 0.5.7; +import "./MarketRegistry.sol"; + +contract MarketRegistryNew is MarketRegistry { + + uint internal bPlotIncentive; + uint internal timeForMaxBonus; + IToken internal bPLOTToken; + + struct MarketCreationIncentiveData { + uint256 plotIncentive; + uint256 bPlotIncentive; + } + + mapping(address => MarketCreationIncentiveData) userIncentives; + event MarketCreationReward(address indexed createdBy, uint256 createdAfter, uint256 plotIncentive, uint256 bPlotIncentive, uint256 gasUsed, uint256 gasCost); + + /** + * @dev Set initial market creation incentive params. + */ + function setInitialCreationIncentives() public { + require(address(bPLOTToken) == address(0)); + timeForMaxBonus = 5 minutes; + bPlotIncentive = 50 ether; + address bPLOTAddress = ms.getLatestAddress("BL"); + bPLOTToken = IToken(bPLOTAddress); + } + + /** + * @dev Creates the new market + * @param _marketType The type of the market. + * @param _marketCurrencyIndex the index of market currency. + */ + function createMarket(uint256 _marketType, uint256 _marketCurrencyIndex) public payable{ + uint256 gasProvided = gasleft(); + address penultimateMarket = marketCreationData[_marketType][_marketCurrencyIndex].penultimateMarket; + if(penultimateMarket != address(0)) { + IMarket(penultimateMarket).settleMarket(); + } + if(marketCreationData[_marketType][_marketCurrencyIndex].marketAddress != address(0)) { + (,,,,,,,, uint _status) = getMarketDetails(marketCreationData[_marketType][_marketCurrencyIndex].marketAddress); + require(_status >= uint(IMarket.PredictionStatus.InSettlement)); + } + (uint8 _roundOfToNearest, bytes32 _currencyName, address _priceFeed) = IMarket(marketCurrencies[_marketCurrencyIndex].marketImplementation).getMarketFeedData(); + marketUtility.update(); + uint64 _marketStartTime = calculateStartTimeForMarket(_marketType, _marketCurrencyIndex); + uint64 _optionRangePerc = marketTypes[_marketType].optionRangePerc; + uint currentPrice = marketUtility.getAssetPriceUSD(_priceFeed); + _optionRangePerc = uint64(currentPrice.mul(_optionRangePerc.div(2)).div(10000)); + uint64 _decimals = marketCurrencies[_marketCurrencyIndex].decimals; + uint64 _minValue = uint64((ceil(currentPrice.sub(_optionRangePerc).div(_roundOfToNearest), 10**_decimals)).mul(_roundOfToNearest)); + uint64 _maxValue = uint64((ceil(currentPrice.add(_optionRangePerc).div(_roundOfToNearest), 10**_decimals)).mul(_roundOfToNearest)); + _createMarket(_marketType, _marketCurrencyIndex, _minValue, _maxValue, _marketStartTime, _currencyName); + // userData[msg.sender].marketsCreated++; + uint256 gasUsed = gasProvided - gasleft(); + _calculateIncentive(gasUsed, _marketStartTime); + } + + function _calculateIncentive(uint256 gasUsed, uint256 _marketStartTime) internal{ + //Adding buffer gas for below calculations + gasUsed = gasUsed + 32000; + uint256 gasCost = gasUsed * tx.gasprice * 10**9; + uint256 incentive = marketUtility.getAssetValueETH(address(plotToken), gasCost); + uint256 bPlotBonus; + uint256 createdAfter = now - _marketStartTime; + if(createdAfter <= timeForMaxBonus) { + bPlotBonus = bPlotIncentive; + } else { + bPlotBonus = bPlotIncentive.div(2); + } + userIncentives[msg.sender] = MarketCreationIncentiveData(incentive, bPlotBonus); + emit MarketCreationReward(msg.sender, createdAfter, incentive, bPlotBonus, gasUsed, gasCost); + } + + + /** + * @dev function to reward user for initiating market creation calls as per the new incetive calculations + */ + function claimCreationRewardV2() external { + uint256 pendingPLOTReward; + pendingPLOTReward = pendingPLOTReward.add(userIncentives[msg.sender].plotIncentive); + require(pendingPLOTReward > 0); + require(plotToken.balanceOf(address(this)) > pendingPLOTReward); + + _transferAsset(address(plotToken), msg.sender, pendingPLOTReward); + _transferAsset(address(bPLOTToken), msg.sender, userIncentives[msg.sender].bPlotIncentive); + } + + + function updateUintParameters(bytes8 code, uint256 value) external onlyAuthorizedToGovern { + if(code == "MCRINC") { // Incentive to be distributed to user for market creation + marketCreationIncentive = value; + } else if(code == "BPLOTINC") { // bPLOT Incentive to be distributed to user for market creation + bPlotIncentive = value; + } else if(code == "MAXBTIME") { // Time before which if market is created, user granted maximum bPLOT bonus + timeForMaxBonus = value; + } else { + marketUtility.updateUintParameters(code, value); + } + } + + /** + * @dev Get uint config parameters + */ + function getUintParameters(bytes8 code) external view returns(bytes8 codeVal, uint256 value) { + if(code == "MCRINC") { + codeVal = code; + value = marketCreationIncentive; + } else if(code == "BPLOTINC") { + codeVal = code; + value = bPlotIncentive; + } else if(code == "MAXBTIME") { + codeVal = code; + value = timeForMaxBonus; + } + } +} From 256759b5ec080d7242879f414a0f7d48a0d647df Mon Sep 17 00:00:00 2001 From: udkreddySomish Date: Mon, 19 Oct 2020 19:18:24 +0530 Subject: [PATCH 07/58] Fetch the current gas price from chainlink and updated calculations --- contracts/MarketRegistryNew.sol | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/contracts/MarketRegistryNew.sol b/contracts/MarketRegistryNew.sol index ecb9335e..9a697ad9 100644 --- a/contracts/MarketRegistryNew.sol +++ b/contracts/MarketRegistryNew.sol @@ -15,12 +15,15 @@ pragma solidity 0.5.7; import "./MarketRegistry.sol"; +import "./interfaces/IChainLinkOracle.sol"; +import "./external/openzeppelin-solidity/math/Math.sol"; contract MarketRegistryNew is MarketRegistry { uint internal bPlotIncentive; uint internal timeForMaxBonus; IToken internal bPLOTToken; + IChainLinkOracle internal clGasPriceAggregator; struct MarketCreationIncentiveData { uint256 plotIncentive; @@ -33,12 +36,13 @@ contract MarketRegistryNew is MarketRegistry { /** * @dev Set initial market creation incentive params. */ - function setInitialCreationIncentives() public { + function setInitialCreationIncentives(address _clGasPriceAggregator) public { require(address(bPLOTToken) == address(0)); timeForMaxBonus = 5 minutes; bPlotIncentive = 50 ether; address bPLOTAddress = ms.getLatestAddress("BL"); bPLOTToken = IToken(bPLOTAddress); + clGasPriceAggregator = IChainLinkOracle(_clGasPriceAggregator); } /** @@ -74,7 +78,7 @@ contract MarketRegistryNew is MarketRegistry { function _calculateIncentive(uint256 gasUsed, uint256 _marketStartTime) internal{ //Adding buffer gas for below calculations gasUsed = gasUsed + 32000; - uint256 gasCost = gasUsed * tx.gasprice * 10**9; + uint256 gasCost = gasUsed.mul(_checkGasPrice()).mul(10**9); uint256 incentive = marketUtility.getAssetValueETH(address(plotToken), gasCost); uint256 bPlotBonus; uint256 createdAfter = now - _marketStartTime; @@ -87,6 +91,12 @@ contract MarketRegistryNew is MarketRegistry { emit MarketCreationReward(msg.sender, createdAfter, incentive, bPlotBonus, gasUsed, gasCost); } + function _checkGasPrice() internal view returns(uint256) { + uint fastGas = uint(clGasPriceAggregator.latestAnswer()); + uint fastGasWithMaxDeviation = fastGas.mul(125).div(100); + return Math.max(Math.min(tx.gasprice,fastGasWithMaxDeviation), fastGas); + } + /** * @dev function to reward user for initiating market creation calls as per the new incetive calculations From ee8f9a908c48add18315a0be362be701d2a3b071 Mon Sep 17 00:00:00 2001 From: udkreddySomish Date: Mon, 19 Oct 2020 20:11:17 +0530 Subject: [PATCH 08/58] Removed bPLOT incentives for market creation --- contracts/MarketRegistryNew.sol | 57 ++++----------------------------- 1 file changed, 7 insertions(+), 50 deletions(-) diff --git a/contracts/MarketRegistryNew.sol b/contracts/MarketRegistryNew.sol index 9a697ad9..6686d872 100644 --- a/contracts/MarketRegistryNew.sol +++ b/contracts/MarketRegistryNew.sol @@ -20,28 +20,21 @@ import "./external/openzeppelin-solidity/math/Math.sol"; contract MarketRegistryNew is MarketRegistry { - uint internal bPlotIncentive; - uint internal timeForMaxBonus; - IToken internal bPLOTToken; IChainLinkOracle internal clGasPriceAggregator; struct MarketCreationIncentiveData { uint256 plotIncentive; - uint256 bPlotIncentive; } mapping(address => MarketCreationIncentiveData) userIncentives; - event MarketCreationReward(address indexed createdBy, uint256 createdAfter, uint256 plotIncentive, uint256 bPlotIncentive, uint256 gasUsed, uint256 gasCost); + event MarketCreationReward(address indexed createdBy, uint256 plotIncentive, uint256 gasUsed, uint256 gasCost); + event ClaimedCreationReward(address indexed user, uint256 plotIncentive); /** * @dev Set initial market creation incentive params. */ - function setInitialCreationIncentives(address _clGasPriceAggregator) public { - require(address(bPLOTToken) == address(0)); - timeForMaxBonus = 5 minutes; - bPlotIncentive = 50 ether; - address bPLOTAddress = ms.getLatestAddress("BL"); - bPLOTToken = IToken(bPLOTAddress); + function setChainLinkGasPriceAggregator(address _clGasPriceAggregator) public { + require(address(clGasPriceAggregator) == address(0)); clGasPriceAggregator = IChainLinkOracle(_clGasPriceAggregator); } @@ -80,15 +73,8 @@ contract MarketRegistryNew is MarketRegistry { gasUsed = gasUsed + 32000; uint256 gasCost = gasUsed.mul(_checkGasPrice()).mul(10**9); uint256 incentive = marketUtility.getAssetValueETH(address(plotToken), gasCost); - uint256 bPlotBonus; - uint256 createdAfter = now - _marketStartTime; - if(createdAfter <= timeForMaxBonus) { - bPlotBonus = bPlotIncentive; - } else { - bPlotBonus = bPlotIncentive.div(2); - } - userIncentives[msg.sender] = MarketCreationIncentiveData(incentive, bPlotBonus); - emit MarketCreationReward(msg.sender, createdAfter, incentive, bPlotBonus, gasUsed, gasCost); + userIncentives[msg.sender] = MarketCreationIncentiveData(incentive); + emit MarketCreationReward(msg.sender, incentive, gasUsed, gasCost); } function _checkGasPrice() internal view returns(uint256) { @@ -106,37 +92,8 @@ contract MarketRegistryNew is MarketRegistry { pendingPLOTReward = pendingPLOTReward.add(userIncentives[msg.sender].plotIncentive); require(pendingPLOTReward > 0); require(plotToken.balanceOf(address(this)) > pendingPLOTReward); - _transferAsset(address(plotToken), msg.sender, pendingPLOTReward); - _transferAsset(address(bPLOTToken), msg.sender, userIncentives[msg.sender].bPlotIncentive); + emit ClaimedCreationReward(msg.sender, pendingPLOTReward); } - - function updateUintParameters(bytes8 code, uint256 value) external onlyAuthorizedToGovern { - if(code == "MCRINC") { // Incentive to be distributed to user for market creation - marketCreationIncentive = value; - } else if(code == "BPLOTINC") { // bPLOT Incentive to be distributed to user for market creation - bPlotIncentive = value; - } else if(code == "MAXBTIME") { // Time before which if market is created, user granted maximum bPLOT bonus - timeForMaxBonus = value; - } else { - marketUtility.updateUintParameters(code, value); - } - } - - /** - * @dev Get uint config parameters - */ - function getUintParameters(bytes8 code) external view returns(bytes8 codeVal, uint256 value) { - if(code == "MCRINC") { - codeVal = code; - value = marketCreationIncentive; - } else if(code == "BPLOTINC") { - codeVal = code; - value = bPlotIncentive; - } else if(code == "MAXBTIME") { - codeVal = code; - value = timeForMaxBonus; - } - } } From f860d923f33649d5181d4e753e80a2b95657d1e0 Mon Sep 17 00:00:00 2001 From: udkreddySomish Date: Tue, 20 Oct 2020 01:48:45 +0530 Subject: [PATCH 09/58] Fixed price conversion issue --- contracts/MarketRegistryNew.sol | 16 ++--- contracts/mock/MockChainLinkGasPriceAgg.sol | 76 +++++++++++++++++++++ 2 files changed, 82 insertions(+), 10 deletions(-) create mode 100644 contracts/mock/MockChainLinkGasPriceAgg.sol diff --git a/contracts/MarketRegistryNew.sol b/contracts/MarketRegistryNew.sol index 6686d872..e648c22e 100644 --- a/contracts/MarketRegistryNew.sol +++ b/contracts/MarketRegistryNew.sol @@ -22,11 +22,7 @@ contract MarketRegistryNew is MarketRegistry { IChainLinkOracle internal clGasPriceAggregator; - struct MarketCreationIncentiveData { - uint256 plotIncentive; - } - - mapping(address => MarketCreationIncentiveData) userIncentives; + mapping(address => uint256) userIncentives; event MarketCreationReward(address indexed createdBy, uint256 plotIncentive, uint256 gasUsed, uint256 gasCost); event ClaimedCreationReward(address indexed user, uint256 plotIncentive); @@ -70,10 +66,10 @@ contract MarketRegistryNew is MarketRegistry { function _calculateIncentive(uint256 gasUsed, uint256 _marketStartTime) internal{ //Adding buffer gas for below calculations - gasUsed = gasUsed + 32000; - uint256 gasCost = gasUsed.mul(_checkGasPrice()).mul(10**9); - uint256 incentive = marketUtility.getAssetValueETH(address(plotToken), gasCost); - userIncentives[msg.sender] = MarketCreationIncentiveData(incentive); + gasUsed = gasUsed + 40000; + uint256 gasCost = gasUsed.mul(_checkGasPrice()); + (, uint256 incentive) = marketUtility.getValueAndMultiplierParameters(ETH_ADDRESS, gasCost); + userIncentives[msg.sender] = incentive; emit MarketCreationReward(msg.sender, incentive, gasUsed, gasCost); } @@ -89,7 +85,7 @@ contract MarketRegistryNew is MarketRegistry { */ function claimCreationRewardV2() external { uint256 pendingPLOTReward; - pendingPLOTReward = pendingPLOTReward.add(userIncentives[msg.sender].plotIncentive); + pendingPLOTReward = pendingPLOTReward.add(userIncentives[msg.sender]); require(pendingPLOTReward > 0); require(plotToken.balanceOf(address(this)) > pendingPLOTReward); _transferAsset(address(plotToken), msg.sender, pendingPLOTReward); diff --git a/contracts/mock/MockChainLinkGasPriceAgg.sol b/contracts/mock/MockChainLinkGasPriceAgg.sol new file mode 100644 index 00000000..a9b2c3c8 --- /dev/null +++ b/contracts/mock/MockChainLinkGasPriceAgg.sol @@ -0,0 +1,76 @@ +pragma solidity 0.5.7; + +import "../interfaces/IChainLinkOracle.sol"; +contract MockChainLinkGasPriceAgg is IChainLinkOracle{ + + int256 latestAns = 45000000000; + uint256 updatedAt = now; + + struct RoundData { + uint80 roundId; + int256 answer; + uint256 startedAt; + uint256 updatedAt; + uint80 answeredInRound; + } + + mapping(uint80 => RoundData) public roundData; + uint80 public currentRound; + + constructor() public { + currentRound = 0; + roundData[0] = RoundData(uint80(0),latestAns, updatedAt, updatedAt, uint80(0)); + } + + function decimals() external view returns (uint8) { + return uint8(8); + } + /** + * @dev Gets the latest answer of chainLink oracle. + * @return int256 representing the latest answer of chainLink oracle. + */ + function latestAnswer() external view returns (int256) + { + return roundData[currentRound].answer; + + } + + /** + * @dev Set the latest answer of chainLink oracle. + * @param _latestAnswer The latest anser of chainLink oracle. + */ + function setLatestAnswer(int256 _latestAnswer) public + { + currentRound = currentRound + uint80(1); + roundData[currentRound] = RoundData(currentRound,_latestAnswer, now, now, currentRound); + } + + function getRoundData(uint80 _roundId) + external + view + returns ( + uint80 roundId, + int256 answer, + uint256 startedAt, + uint256 updatedAt, + uint80 answeredInRound + ) { + return (roundData[_roundId].roundId, roundData[_roundId].answer, roundData[_roundId].startedAt, + roundData[_roundId].updatedAt,roundData[_roundId].answeredInRound); + } + + function latestRoundData() + external + view + returns ( + uint80 roundId, + int256 answer, + uint256 startedAt, + uint256 updatedAt, + uint80 answeredInRound + ) { + return (roundData[currentRound].roundId, roundData[currentRound].answer, roundData[currentRound].startedAt, + roundData[currentRound].updatedAt,roundData[currentRound].answeredInRound); + } + +} \ No newline at end of file From 6a972081d673b1ff2d0eec8617f9210e15cfb99c Mon Sep 17 00:00:00 2001 From: udkreddySomish Date: Tue, 20 Oct 2020 01:48:58 +0530 Subject: [PATCH 10/58] Updated testcases --- migrations/2_deploy.js | 4 + test/24_UpgradedCreationIncentive.test.js | 183 ++++++++++++++++++++++ 2 files changed, 187 insertions(+) create mode 100644 test/24_UpgradedCreationIncentive.test.js diff --git a/migrations/2_deploy.js b/migrations/2_deploy.js index e2bd7c41..1a828514 100644 --- a/migrations/2_deploy.js +++ b/migrations/2_deploy.js @@ -66,6 +66,10 @@ module.exports = function(deployer, network, accounts){ // console.log(await plotus.getOpenMarkets()); await plotusToken.transfer(uniswapRouter.address, "100000000000000000000"); await plotusToken.transfer(plotus.address, "10000000000000000000000"); + // await blotToken.addMinter(plotusAddress); + // await plotusToken.approve(blotToken.address, "1000000000000000000000000000"); + // await blotToken.mint(plotus.address, "10000000000000000000000"); + // await plotus.setInitialCreationIncentives(); }); }; diff --git a/test/24_UpgradedCreationIncentive.test.js b/test/24_UpgradedCreationIncentive.test.js new file mode 100644 index 00000000..974cc61e --- /dev/null +++ b/test/24_UpgradedCreationIncentive.test.js @@ -0,0 +1,183 @@ +const { assert } = require("chai"); +const OwnedUpgradeabilityProxy = artifacts.require("OwnedUpgradeabilityProxy"); +const Market = artifacts.require("MockMarket"); +const Plotus = artifacts.require("MarketRegistry"); +const MarketRegistryNew = artifacts.require("MarketRegistryNew"); +const MockChainLinkGasPriceAgg = artifacts.require("MockChainLinkGasPriceAgg"); +const Master = artifacts.require("Master"); +const MemberRoles = artifacts.require("MemberRoles"); +const PlotusToken = artifacts.require("MockPLOT"); +const MockWeth = artifacts.require("MockWeth"); +const MarketUtility = artifacts.require("MarketUtility"); +const MockConfig = artifacts.require("MockConfig"); +const Governance = artifacts.require("Governance"); +const MockUniswapRouter = artifacts.require("MockUniswapRouter"); +const MockUniswapV2Pair = artifacts.require("MockUniswapV2Pair"); +const MockUniswapFactory = artifacts.require('MockUniswapFactory'); +const TokenController = artifacts.require("MockTokenController"); +const web3 = Market.web3; +const increaseTime = require("./utils/increaseTime.js").increaseTime; +const assertRevert = require("./utils/assertRevert").assertRevert; +const latestTime = require("./utils/latestTime").latestTime; +const encode = require('./utils/encoder.js').encode; +const encode1 = require('./utils/encoder.js').encode1; +const {toHex, toWei, toChecksumAddress} = require('./utils/ethTools'); +const gvProposal = require('./utils/gvProposal.js').gvProposalWithIncentiveViaTokenHolder; + +var initialPLOTPrice; +var initialEthPrice; +var eventData; +const ethAddress = "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE"; +var nullAddress = "0x0000000000000000000000000000000000000000"; + +contract("MarketUtility", async function([user1, user2, user3, user4, user5, user6, user7, user8, user9, user10, user11, user12]) { + let masterInstance, + plotusToken, + marketConfig, + MockUniswapRouterInstance, + tokenControllerAdd, + tokenController, + plotusNewAddress, + plotusNewInstance, governance, + mockUniswapV2Pair, + mockUniswapFactory, weth, + chainlinkGasAgg; + before(async () => { + masterInstance = await OwnedUpgradeabilityProxy.deployed(); + masterInstance = await Master.at(masterInstance.address); + plotusToken = await PlotusToken.deployed(); + tokenControllerAdd = await masterInstance.getLatestAddress(web3.utils.toHex("TC")); + tokenController = await TokenController.at(tokenControllerAdd); + plotusNewAddress = await masterInstance.getLatestAddress(web3.utils.toHex("PL")); + memberRoles = await masterInstance.getLatestAddress(web3.utils.toHex("MR")); + memberRoles = await MemberRoles.at(memberRoles); + governance = await masterInstance.getLatestAddress(web3.utils.toHex("GV")); + governance = await Governance.at(governance); + MockUniswapRouterInstance = await MockUniswapRouter.deployed(); + mockUniswapFactory = await MockUniswapFactory.deployed(); + plotusNewInstance = await Plotus.at(plotusNewAddress); + marketConfig = await plotusNewInstance.marketUtility(); + marketConfig = await MockConfig.at(marketConfig); + weth = await MockWeth.deployed(); + await marketConfig.setWeth(weth.address); + }); + + it('Should Update Existing Market utility Implementation', async function() { + let newUtility = await MarketUtility.new(); + let existingMarkets = await plotusNewInstance.getOpenMarkets(); + let actionHash = encode( + 'upgradeContractImplementation(address,address)', + marketConfig.address, + newUtility.address + ); + await gvProposal( + 6, + actionHash, + await MemberRoles.at(await masterInstance.getLatestAddress(toHex('MR'))), + governance, + 2, + 0 + ); + await increaseTime(604800); + marketConfig = await MarketUtility.at(marketConfig.address); + }); + + it("Deploy uniswap v2 pair and add liquidity", async function() { + mockUniswapV2Pair = await MockUniswapV2Pair.new(); + await mockUniswapV2Pair.initialize(plotusToken.address, weth.address); + await weth.deposit({from: user12, value: toWei(10)}); + await weth.transfer(mockUniswapV2Pair.address, toWei(10),{from: user12}); + await plotusToken.transfer(mockUniswapV2Pair.address, toWei(1000)); + initialPLOTPrice = 1000/10; + initialEthPrice = 10/1000; + await mockUniswapFactory.setPair(mockUniswapV2Pair.address); + await mockUniswapV2Pair.sync(); + await marketConfig.setInitialCummulativePrice(); + }); + + it("Should create Markets", async function() { + await mockUniswapV2Pair.sync(); + await increaseTime(3610); + await plotusNewInstance.createMarket(0,0); + await plotusNewInstance.createMarket(0,1); + }); + + it('Should Update Market Registry Implementation', async function() { + let newRegistry = await MarketRegistryNew.new(); + let actionHash = encode1( + ['bytes2[]', 'address[]'], + [ + [toHex('PL')], + [newRegistry.address] + ] + ); + await gvProposal( + 7, + actionHash, + await MemberRoles.at(await masterInstance.getLatestAddress(toHex('MR'))), + governance, + 2, + 0 + ); + await increaseTime(604800); + plotusNewInstance = await MarketRegistryNew.at(plotusNewInstance.address); + }); + + it("Should setup initial params for new regitsry", async function() { + chainlinkGasAgg = await MockChainLinkGasPriceAgg.new(); + await plotusNewInstance.setChainLinkGasPriceAggregator(chainlinkGasAgg.address); + }); + + it("Should be able to claim market creation rewards of pre upgrade", async function() { + let oldBalance = parseFloat(await plotusToken.balanceOf(user1)); + await plotusNewInstance.claimCreationReward(); + let newBalance = parseFloat(await plotusToken.balanceOf(user1)); + assert.isAbove(newBalance/1,oldBalance/1); + }); + + it("Should create Markets", async function() { + await mockUniswapV2Pair.sync(); + await increaseTime(3610); + await plotusNewInstance.createMarket(0,0); + let tx = await plotusNewInstance.createMarket(0,1, {gasPrice:45}); + eventData = tx.logs[2].args; + }); + + it("If gas is provided less than fastgas price from oracle, reward should be as per fast gas", async function() { + let gasUsed = eventData.gasUsed.toNumber(); + let gasPrice = await chainlinkGasAgg.latestAnswer(); + estimatedGasCost = gasPrice*gasUsed; + let costInETH = estimatedGasCost; + console.log(costInETH); + let worthInPLOT = await marketConfig.getValueAndMultiplierParameters(ethAddress, costInETH + ""); + assert.equal(eventData.plotIncentive/1, worthInPLOT[1]/1); + // await plotusNewInstance.claimCreationRewardV2(); + }); + + // it("If gas is provided upto 125% of fast gas, reward should be as per provided gas", async function() { + // await increaseTime(3610); + // let tx = await plotusNewInstance.createMarket(0,1, {gasPrice:56.25}); + // eventData = tx.logs[2].args; + // let gasUsed = eventData.gasUsed.toNumber(); + // let gasPrice = 56.25*10^9; + // estimatedGasCost = gasPrice*gasUsed; + // let costInETH = estimatedGasCost; + // console.log(costInETH); + // let worthInPLOT = await marketConfig.getValueAndMultiplierParameters(ethAddress, costInETH + ""); + // assert.equal(eventData.plotIncentive/1, worthInPLOT[1]/1) + // }); + + // it("If gas is provided more than 125% of fast gas, reward should be as per provided gas", async function() { + // await increaseTime(3610); + // let tx = await plotusNewInstance.createMarket(0,1, {gasPrice:100}); + // eventData = tx.logs[2].args; + // let gasUsed = eventData.gasUsed.toNumber(); + // let gasPrice = 56.25*10^9; + // estimatedGasCost = gasPrice*gasUsed; + // let costInETH = estimatedGasCost; + // console.log(costInETH); + // let worthInPLOT = await marketConfig.getValueAndMultiplierParameters(ethAddress, costInETH + ""); + // assert.equal(eventData.plotIncentive/1, worthInPLOT[1]/1) + // }); + +}); From a655293ecd5cb37168e8dd78f2c4a41cdf284dfe Mon Sep 17 00:00:00 2001 From: udkreddySomish Date: Tue, 20 Oct 2020 15:14:02 +0530 Subject: [PATCH 11/58] Updated buffer gas amount, and minor fixes --- contracts/MarketRegistryNew.sol | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/contracts/MarketRegistryNew.sol b/contracts/MarketRegistryNew.sol index e648c22e..35ca24ee 100644 --- a/contracts/MarketRegistryNew.sol +++ b/contracts/MarketRegistryNew.sol @@ -66,10 +66,10 @@ contract MarketRegistryNew is MarketRegistry { function _calculateIncentive(uint256 gasUsed, uint256 _marketStartTime) internal{ //Adding buffer gas for below calculations - gasUsed = gasUsed + 40000; + gasUsed = gasUsed + 38500; uint256 gasCost = gasUsed.mul(_checkGasPrice()); (, uint256 incentive) = marketUtility.getValueAndMultiplierParameters(ETH_ADDRESS, gasCost); - userIncentives[msg.sender] = incentive; + userIncentives[msg.sender] = userIncentives[msg.sender].add(incentive); emit MarketCreationReward(msg.sender, incentive, gasUsed, gasCost); } @@ -84,12 +84,12 @@ contract MarketRegistryNew is MarketRegistry { * @dev function to reward user for initiating market creation calls as per the new incetive calculations */ function claimCreationRewardV2() external { - uint256 pendingPLOTReward; - pendingPLOTReward = pendingPLOTReward.add(userIncentives[msg.sender]); + uint256 pendingPLOTReward = userIncentives[msg.sender]; require(pendingPLOTReward > 0); require(plotToken.balanceOf(address(this)) > pendingPLOTReward); _transferAsset(address(plotToken), msg.sender, pendingPLOTReward); emit ClaimedCreationReward(msg.sender, pendingPLOTReward); + delete userIncentives[msg.sender]; } } From 4495eec1935e78dde0269dbce142aac5b7d9f926 Mon Sep 17 00:00:00 2001 From: udkreddySomish Date: Tue, 20 Oct 2020 15:14:27 +0530 Subject: [PATCH 12/58] Updated testcases for new market creation incentives --- test/24_UpgradedCreationIncentive.test.js | 78 +++++++++++++++-------- 1 file changed, 50 insertions(+), 28 deletions(-) diff --git a/test/24_UpgradedCreationIncentive.test.js b/test/24_UpgradedCreationIncentive.test.js index 974cc61e..75bce8de 100644 --- a/test/24_UpgradedCreationIncentive.test.js +++ b/test/24_UpgradedCreationIncentive.test.js @@ -27,6 +27,7 @@ const gvProposal = require('./utils/gvProposal.js').gvProposalWithIncentiveViaTo var initialPLOTPrice; var initialEthPrice; var eventData; +var incentivesGained = 0; const ethAddress = "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE"; var nullAddress = "0x0000000000000000000000000000000000000000"; @@ -131,15 +132,20 @@ contract("MarketUtility", async function([user1, user2, user3, user4, user5, use it("Should be able to claim market creation rewards of pre upgrade", async function() { let oldBalance = parseFloat(await plotusToken.balanceOf(user1)); await plotusNewInstance.claimCreationReward(); + // await plotusNewInstance.claimCreationRewardV2(); let newBalance = parseFloat(await plotusToken.balanceOf(user1)); assert.isAbove(newBalance/1,oldBalance/1); }); + it("Should not be able to claim the market creation rewards if not created any market", async function() { + let tx = await assertRevert(plotusNewInstance.claimCreationRewardV2()); + }); + it("Should create Markets", async function() { await mockUniswapV2Pair.sync(); await increaseTime(3610); - await plotusNewInstance.createMarket(0,0); - let tx = await plotusNewInstance.createMarket(0,1, {gasPrice:45}); + let tx = await plotusNewInstance.createMarket(0,1, {gasPrice:30000000000}); + // console.log(tx.receipt.gasUsed); eventData = tx.logs[2].args; }); @@ -148,36 +154,52 @@ contract("MarketUtility", async function([user1, user2, user3, user4, user5, use let gasPrice = await chainlinkGasAgg.latestAnswer(); estimatedGasCost = gasPrice*gasUsed; let costInETH = estimatedGasCost; - console.log(costInETH); + // console.log(gasUsed); + // console.log(costInETH); let worthInPLOT = await marketConfig.getValueAndMultiplierParameters(ethAddress, costInETH + ""); + incentivesGained += eventData.plotIncentive/1; assert.equal(eventData.plotIncentive/1, worthInPLOT[1]/1); - // await plotusNewInstance.claimCreationRewardV2(); }); - // it("If gas is provided upto 125% of fast gas, reward should be as per provided gas", async function() { - // await increaseTime(3610); - // let tx = await plotusNewInstance.createMarket(0,1, {gasPrice:56.25}); - // eventData = tx.logs[2].args; - // let gasUsed = eventData.gasUsed.toNumber(); - // let gasPrice = 56.25*10^9; - // estimatedGasCost = gasPrice*gasUsed; - // let costInETH = estimatedGasCost; - // console.log(costInETH); - // let worthInPLOT = await marketConfig.getValueAndMultiplierParameters(ethAddress, costInETH + ""); - // assert.equal(eventData.plotIncentive/1, worthInPLOT[1]/1) - // }); + it("If gas is provided upto 125% of fast gas, reward should be as per provided gas", async function() { + await increaseTime(3610); + let tx = await plotusNewInstance.createMarket(0,1, {gasPrice:50000000000}); + eventData = tx.logs[2].args; + let gasUsed = eventData.gasUsed.toNumber(); + let gasPrice = 50000000000; + estimatedGasCost = gasPrice*gasUsed; + let costInETH = estimatedGasCost; + // console.log(gasUsed); + // console.log(tx.receipt.gasUsed); + // console.log(costInETH); + let worthInPLOT = await marketConfig.getValueAndMultiplierParameters(ethAddress, costInETH + ""); + incentivesGained += eventData.plotIncentive/1; + assert.equal(eventData.plotIncentive/1, worthInPLOT[1]/1) + }); + + it("If gas is provided more than 125% of fast gas, reward should be as per provided gas", async function() { + await increaseTime(3610); + let tx = await plotusNewInstance.createMarket(0,1, {gasPrice:100000000000}); + eventData = tx.logs[2].args; + let gasUsed = eventData.gasUsed.toNumber(); + let gasPrice = 56250000000; + estimatedGasCost = gasPrice*gasUsed; + let costInETH = estimatedGasCost; + // console.log(gasUsed); + // console.log(tx.receipt.gasUsed); + // console.log(costInETH); + let worthInPLOT = await marketConfig.getValueAndMultiplierParameters(ethAddress, costInETH + ""); + incentivesGained += eventData.plotIncentive/1; + assert.equal(eventData.plotIncentive/1, worthInPLOT[1]/1) + }); - // it("If gas is provided more than 125% of fast gas, reward should be as per provided gas", async function() { - // await increaseTime(3610); - // let tx = await plotusNewInstance.createMarket(0,1, {gasPrice:100}); - // eventData = tx.logs[2].args; - // let gasUsed = eventData.gasUsed.toNumber(); - // let gasPrice = 56.25*10^9; - // estimatedGasCost = gasPrice*gasUsed; - // let costInETH = estimatedGasCost; - // console.log(costInETH); - // let worthInPLOT = await marketConfig.getValueAndMultiplierParameters(ethAddress, costInETH + ""); - // assert.equal(eventData.plotIncentive/1, worthInPLOT[1]/1) - // }); + it("Should be able to claim the market creation rewards", async function() { + let oldBalance = parseFloat(await plotusToken.balanceOf(user1)); + let tx = await plotusNewInstance.claimCreationRewardV2(); + let newBalance = parseFloat(await plotusToken.balanceOf(user1)); + // console.log(tx.logs[0].args); + // console.log(newBalance); + assert.equal(newBalance/1, oldBalance/1 + incentivesGained); + }); }); From 899d4652f1a3800f11c930b9a164b81702d0c2e2 Mon Sep 17 00:00:00 2001 From: udkreddySomish Date: Tue, 20 Oct 2020 19:54:29 +0530 Subject: [PATCH 13/58] Updated incentive formulae and added authorized address check for setting initial params --- contracts/MarketRegistryNew.sol | 50 +++++++++++++++++++---- test/24_UpgradedCreationIncentive.test.js | 26 ++++++++++-- 2 files changed, 65 insertions(+), 11 deletions(-) diff --git a/contracts/MarketRegistryNew.sol b/contracts/MarketRegistryNew.sol index 35ca24ee..bfbb6dac 100644 --- a/contracts/MarketRegistryNew.sol +++ b/contracts/MarketRegistryNew.sol @@ -20,18 +20,21 @@ import "./external/openzeppelin-solidity/math/Math.sol"; contract MarketRegistryNew is MarketRegistry { - IChainLinkOracle internal clGasPriceAggregator; + uint256 internal maxGasPrice; + IChainLinkOracle public clGasPriceAggregator; mapping(address => uint256) userIncentives; - event MarketCreationReward(address indexed createdBy, uint256 plotIncentive, uint256 gasUsed, uint256 gasCost); - event ClaimedCreationReward(address indexed user, uint256 plotIncentive); + event MarketCreationReward(address indexed createdBy, uint256 plotIncentive, uint256 gasUsed, uint256 gasCost, uint256 gasPriceConsidered, uint256 gasPriceGiven, uint256 maxGasCap); + event ClaimedMarketCreationReward(address indexed user, uint256 plotIncentive); /** * @dev Set initial market creation incentive params. */ - function setChainLinkGasPriceAggregator(address _clGasPriceAggregator) public { + function setGasPriceAggAndMaxGas(address _clGasPriceAggregator) external { require(address(clGasPriceAggregator) == address(0)); + require(msg.sender == marketInitiater); clGasPriceAggregator = IChainLinkOracle(_clGasPriceAggregator); + maxGasPrice = 100 * 10**9; } /** @@ -67,16 +70,17 @@ contract MarketRegistryNew is MarketRegistry { function _calculateIncentive(uint256 gasUsed, uint256 _marketStartTime) internal{ //Adding buffer gas for below calculations gasUsed = gasUsed + 38500; - uint256 gasCost = gasUsed.mul(_checkGasPrice()); + uint256 gasPrice = _checkGasPrice(); + uint256 gasCost = gasUsed.mul(gasPrice); (, uint256 incentive) = marketUtility.getValueAndMultiplierParameters(ETH_ADDRESS, gasCost); userIncentives[msg.sender] = userIncentives[msg.sender].add(incentive); - emit MarketCreationReward(msg.sender, incentive, gasUsed, gasCost); + emit MarketCreationReward(msg.sender, incentive, gasUsed, gasCost, gasPrice, tx.gasprice, maxGasPrice); } function _checkGasPrice() internal view returns(uint256) { uint fastGas = uint(clGasPriceAggregator.latestAnswer()); uint fastGasWithMaxDeviation = fastGas.mul(125).div(100); - return Math.max(Math.min(tx.gasprice,fastGasWithMaxDeviation), fastGas); + return Math.min(Math.min(tx.gasprice,fastGasWithMaxDeviation), maxGasPrice); } @@ -88,8 +92,38 @@ contract MarketRegistryNew is MarketRegistry { require(pendingPLOTReward > 0); require(plotToken.balanceOf(address(this)) > pendingPLOTReward); _transferAsset(address(plotToken), msg.sender, pendingPLOTReward); - emit ClaimedCreationReward(msg.sender, pendingPLOTReward); + emit ClaimedMarketCreationReward(msg.sender, pendingPLOTReward); delete userIncentives[msg.sender]; } + function updateConfigAddressParameters(bytes8 code, address payable value) external onlyAuthorizedToGovern { + if(code == "GASAGG") { // Incentive to be distributed to user for market creation + clGasPriceAggregator = IChainLinkOracle(value); + } else { + marketUtility.updateAddressParameters(code, value); + } + } + + function updateUintParameters(bytes8 code, uint256 value) external onlyAuthorizedToGovern { + if(code == "MCRINC") { // Incentive to be distributed to user for market creation + marketCreationIncentive = value; + } else if(code == "MAXGAS") { // Maximum gas upto which is considered while calculating market creation incentives + maxGasPrice = value; + } else { + marketUtility.updateUintParameters(code, value); + } + } + + /** + * @dev Get uint config parameters + */ + function getUintParameters(bytes8 code) external view returns(bytes8 codeVal, uint256 value) { + codeVal = code; + if(code == "MCRINC") { + value = marketCreationIncentive; + } else if(code == "MAXGAS") { + value = maxGasPrice; + } + } + } diff --git a/test/24_UpgradedCreationIncentive.test.js b/test/24_UpgradedCreationIncentive.test.js index 75bce8de..e01be7a3 100644 --- a/test/24_UpgradedCreationIncentive.test.js +++ b/test/24_UpgradedCreationIncentive.test.js @@ -126,7 +126,8 @@ contract("MarketUtility", async function([user1, user2, user3, user4, user5, use it("Should setup initial params for new regitsry", async function() { chainlinkGasAgg = await MockChainLinkGasPriceAgg.new(); - await plotusNewInstance.setChainLinkGasPriceAggregator(chainlinkGasAgg.address); + await assertRevert(plotusNewInstance.setGasPriceAggAndMaxGas(chainlinkGasAgg.address, {from:user2})); + await plotusNewInstance.setGasPriceAggAndMaxGas(chainlinkGasAgg.address); }); it("Should be able to claim market creation rewards of pre upgrade", async function() { @@ -149,9 +150,10 @@ contract("MarketUtility", async function([user1, user2, user3, user4, user5, use eventData = tx.logs[2].args; }); - it("If gas is provided less than fastgas price from oracle, reward should be as per fast gas", async function() { + it("If gas is provided less than fastgas price from oracle, reward should be as per minimum of fast gas and provided gas", async function() { let gasUsed = eventData.gasUsed.toNumber(); let gasPrice = await chainlinkGasAgg.latestAnswer(); + gasPrice = Math.min(30000000000, gasPrice); estimatedGasCost = gasPrice*gasUsed; let costInETH = estimatedGasCost; // console.log(gasUsed); @@ -177,7 +179,7 @@ contract("MarketUtility", async function([user1, user2, user3, user4, user5, use assert.equal(eventData.plotIncentive/1, worthInPLOT[1]/1) }); - it("If gas is provided more than 125% of fast gas, reward should be as per provided gas", async function() { + it("If gas is provided more than 125% of fast gas, reward should be as per 125% fast gas", async function() { await increaseTime(3610); let tx = await plotusNewInstance.createMarket(0,1, {gasPrice:100000000000}); eventData = tx.logs[2].args; @@ -193,6 +195,24 @@ contract("MarketUtility", async function([user1, user2, user3, user4, user5, use assert.equal(eventData.plotIncentive/1, worthInPLOT[1]/1) }); + it("If gas is provided more than 125% of fast gas and maxGas price, reward should be as per minimum of 125% of fast gas or max gasprice", async function() { + await chainlinkGasAgg.setLatestAnswer(125000000000); + await increaseTime(3610); + let tx = await plotusNewInstance.createMarket(0,1, {gasPrice:150000000000}); + eventData = tx.logs[2].args; + let gasUsed = eventData.gasUsed.toNumber(); + let maxGas = await plotusNewInstance.getUintParameters(toHex("MAXGAS")); + let gasPrice = maxGas[1].toNumber(); + estimatedGasCost = gasPrice*gasUsed; + let costInETH = estimatedGasCost; + // console.log(gasUsed); + // console.log(tx.receipt.gasUsed); + // console.log(costInETH); + let worthInPLOT = await marketConfig.getValueAndMultiplierParameters(ethAddress, costInETH + ""); + incentivesGained += eventData.plotIncentive/1; + assert.equal(eventData.plotIncentive/1, worthInPLOT[1]/1) + }); + it("Should be able to claim the market creation rewards", async function() { let oldBalance = parseFloat(await plotusToken.balanceOf(user1)); let tx = await plotusNewInstance.claimCreationRewardV2(); From 9a5c7adb0deaeebb91b4daf47e6a4758de0da5cd Mon Sep 17 00:00:00 2001 From: udkreddySomish Date: Tue, 20 Oct 2020 20:13:40 +0530 Subject: [PATCH 14/58] Added code comments --- contracts/MarketRegistryNew.sol | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/contracts/MarketRegistryNew.sol b/contracts/MarketRegistryNew.sol index bfbb6dac..43b840af 100644 --- a/contracts/MarketRegistryNew.sol +++ b/contracts/MarketRegistryNew.sol @@ -67,6 +67,9 @@ contract MarketRegistryNew is MarketRegistry { _calculateIncentive(gasUsed, _marketStartTime); } + /** + * @dev internal function to calculate user incentive for market creation + */ function _calculateIncentive(uint256 gasUsed, uint256 _marketStartTime) internal{ //Adding buffer gas for below calculations gasUsed = gasUsed + 38500; @@ -77,6 +80,9 @@ contract MarketRegistryNew is MarketRegistry { emit MarketCreationReward(msg.sender, incentive, gasUsed, gasCost, gasPrice, tx.gasprice, maxGasPrice); } + /** + * @dev internal function to calculate gas price for market creation incetives + */ function _checkGasPrice() internal view returns(uint256) { uint fastGas = uint(clGasPriceAggregator.latestAnswer()); uint fastGasWithMaxDeviation = fastGas.mul(125).div(100); @@ -96,6 +102,9 @@ contract MarketRegistryNew is MarketRegistry { delete userIncentives[msg.sender]; } + /** + * @dev function to update address parameters of market + */ function updateConfigAddressParameters(bytes8 code, address payable value) external onlyAuthorizedToGovern { if(code == "GASAGG") { // Incentive to be distributed to user for market creation clGasPriceAggregator = IChainLinkOracle(value); @@ -104,6 +113,9 @@ contract MarketRegistryNew is MarketRegistry { } } + /** + * @dev function to update integer parameters of market + */ function updateUintParameters(bytes8 code, uint256 value) external onlyAuthorizedToGovern { if(code == "MCRINC") { // Incentive to be distributed to user for market creation marketCreationIncentive = value; From 91000c9fb54248a764bda4cf9d60fbbcb5180b42 Mon Sep 17 00:00:00 2001 From: udkreddySomish Date: Tue, 20 Oct 2020 21:48:49 +0530 Subject: [PATCH 15/58] Corrected comments --- contracts/MarketRegistryNew.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/MarketRegistryNew.sol b/contracts/MarketRegistryNew.sol index 43b840af..1fb91f1b 100644 --- a/contracts/MarketRegistryNew.sol +++ b/contracts/MarketRegistryNew.sol @@ -81,7 +81,7 @@ contract MarketRegistryNew is MarketRegistry { } /** - * @dev internal function to calculate gas price for market creation incetives + * @dev internal function to calculate gas price for market creation incentives */ function _checkGasPrice() internal view returns(uint256) { uint fastGas = uint(clGasPriceAggregator.latestAnswer()); From 5cfa0d8b2b86b51de9d8cba0909c808f9403bb1b Mon Sep 17 00:00:00 2001 From: udkreddySomish Date: Tue, 20 Oct 2020 21:53:25 +0530 Subject: [PATCH 16/58] Increased default balance in coverage script --- .solcover.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.solcover.js b/.solcover.js index 58941407..16f51fcb 100644 --- a/.solcover.js +++ b/.solcover.js @@ -1,7 +1,7 @@ module.exports = { skipFiles: ['external', 'mock', 'interfaces', 'marketImplementations'], providerOptions: { - default_balance_ether: 110, // Extra zero, coverage consumes more gas + default_balance_ether: 1100, // Extra zero, coverage consumes more gas network_id: 5777, mnemonic: 'grocery obvious wire insane limit weather parade parrot patrol stock blast ivory', From a450e1fa3818b52e5bc7b537858b71c7a5c3192d Mon Sep 17 00:00:00 2001 From: udkreddySomish Date: Tue, 20 Oct 2020 22:18:49 +0530 Subject: [PATCH 17/58] Increased default balance in coverage script --- .solcover.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.solcover.js b/.solcover.js index 16f51fcb..1ec118f3 100644 --- a/.solcover.js +++ b/.solcover.js @@ -1,7 +1,7 @@ module.exports = { skipFiles: ['external', 'mock', 'interfaces', 'marketImplementations'], providerOptions: { - default_balance_ether: 1100, // Extra zero, coverage consumes more gas + default_balance_ether: 50000000, // Extra zero, coverage consumes more gas network_id: 5777, mnemonic: 'grocery obvious wire insane limit weather parade parrot patrol stock blast ivory', From 5b409136631a863d9fbfdbf7383359fc18430f5a Mon Sep 17 00:00:00 2001 From: udkreddySomish Date: Tue, 20 Oct 2020 22:55:53 +0530 Subject: [PATCH 18/58] Removed commented code --- contracts/MarketRegistryNew.sol | 1 - 1 file changed, 1 deletion(-) diff --git a/contracts/MarketRegistryNew.sol b/contracts/MarketRegistryNew.sol index 1fb91f1b..cd6b6ff5 100644 --- a/contracts/MarketRegistryNew.sol +++ b/contracts/MarketRegistryNew.sol @@ -62,7 +62,6 @@ contract MarketRegistryNew is MarketRegistry { uint64 _minValue = uint64((ceil(currentPrice.sub(_optionRangePerc).div(_roundOfToNearest), 10**_decimals)).mul(_roundOfToNearest)); uint64 _maxValue = uint64((ceil(currentPrice.add(_optionRangePerc).div(_roundOfToNearest), 10**_decimals)).mul(_roundOfToNearest)); _createMarket(_marketType, _marketCurrencyIndex, _minValue, _maxValue, _marketStartTime, _currencyName); - // userData[msg.sender].marketsCreated++; uint256 gasUsed = gasProvided - gasleft(); _calculateIncentive(gasUsed, _marketStartTime); } From afec03d1a3a7e0525e65b42b5e2c801af3c39a37 Mon Sep 17 00:00:00 2001 From: udkreddySomish Date: Wed, 21 Oct 2020 11:57:50 +0530 Subject: [PATCH 19/58] Removed unused argument --- contracts/MarketRegistryNew.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contracts/MarketRegistryNew.sol b/contracts/MarketRegistryNew.sol index cd6b6ff5..6aeb98c3 100644 --- a/contracts/MarketRegistryNew.sol +++ b/contracts/MarketRegistryNew.sol @@ -63,13 +63,13 @@ contract MarketRegistryNew is MarketRegistry { uint64 _maxValue = uint64((ceil(currentPrice.add(_optionRangePerc).div(_roundOfToNearest), 10**_decimals)).mul(_roundOfToNearest)); _createMarket(_marketType, _marketCurrencyIndex, _minValue, _maxValue, _marketStartTime, _currencyName); uint256 gasUsed = gasProvided - gasleft(); - _calculateIncentive(gasUsed, _marketStartTime); + _calculateIncentive(gasUsed); } /** * @dev internal function to calculate user incentive for market creation */ - function _calculateIncentive(uint256 gasUsed, uint256 _marketStartTime) internal{ + function _calculateIncentive(uint256 gasUsed) internal{ //Adding buffer gas for below calculations gasUsed = gasUsed + 38500; uint256 gasPrice = _checkGasPrice(); From bb552f80472c7e68333c14535bb3d8364738c7b5 Mon Sep 17 00:00:00 2001 From: udkreddySomish Date: Wed, 21 Oct 2020 11:58:50 +0530 Subject: [PATCH 20/58] Covergae: Fixed issue with high gas while running coverage --- .solcover.js | 2 +- test/24_UpgradedCreationIncentive.test.js | 23 ++++++++++++----------- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/.solcover.js b/.solcover.js index 1ec118f3..588b29c6 100644 --- a/.solcover.js +++ b/.solcover.js @@ -1,7 +1,7 @@ module.exports = { skipFiles: ['external', 'mock', 'interfaces', 'marketImplementations'], providerOptions: { - default_balance_ether: 50000000, // Extra zero, coverage consumes more gas + default_balance_ether: 5000, // Extra zero, coverage consumes more gas network_id: 5777, mnemonic: 'grocery obvious wire insane limit weather parade parrot patrol stock blast ivory', diff --git a/test/24_UpgradedCreationIncentive.test.js b/test/24_UpgradedCreationIncentive.test.js index e01be7a3..a8f65213 100644 --- a/test/24_UpgradedCreationIncentive.test.js +++ b/test/24_UpgradedCreationIncentive.test.js @@ -29,7 +29,7 @@ var initialEthPrice; var eventData; var incentivesGained = 0; const ethAddress = "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE"; -var nullAddress = "0x0000000000000000000000000000000000000000"; +var nullAddress = "0x0000000000000000000000000000"; contract("MarketUtility", async function([user1, user2, user3, user4, user5, user6, user7, user8, user9, user10, user11, user12]) { let masterInstance, @@ -143,9 +143,10 @@ contract("MarketUtility", async function([user1, user2, user3, user4, user5, use }); it("Should create Markets", async function() { + await chainlinkGasAgg.setLatestAnswer(45000000); await mockUniswapV2Pair.sync(); await increaseTime(3610); - let tx = await plotusNewInstance.createMarket(0,1, {gasPrice:30000000000}); + let tx = await plotusNewInstance.createMarket(0,1, {gasPrice:30000000}); // console.log(tx.receipt.gasUsed); eventData = tx.logs[2].args; }); @@ -153,7 +154,7 @@ contract("MarketUtility", async function([user1, user2, user3, user4, user5, use it("If gas is provided less than fastgas price from oracle, reward should be as per minimum of fast gas and provided gas", async function() { let gasUsed = eventData.gasUsed.toNumber(); let gasPrice = await chainlinkGasAgg.latestAnswer(); - gasPrice = Math.min(30000000000, gasPrice); + gasPrice = Math.min(30000000, gasPrice); estimatedGasCost = gasPrice*gasUsed; let costInETH = estimatedGasCost; // console.log(gasUsed); @@ -165,10 +166,10 @@ contract("MarketUtility", async function([user1, user2, user3, user4, user5, use it("If gas is provided upto 125% of fast gas, reward should be as per provided gas", async function() { await increaseTime(3610); - let tx = await plotusNewInstance.createMarket(0,1, {gasPrice:50000000000}); + let tx = await plotusNewInstance.createMarket(0,1, {gasPrice:50000000}); eventData = tx.logs[2].args; let gasUsed = eventData.gasUsed.toNumber(); - let gasPrice = 50000000000; + let gasPrice = 50000000; estimatedGasCost = gasPrice*gasUsed; let costInETH = estimatedGasCost; // console.log(gasUsed); @@ -181,10 +182,10 @@ contract("MarketUtility", async function([user1, user2, user3, user4, user5, use it("If gas is provided more than 125% of fast gas, reward should be as per 125% fast gas", async function() { await increaseTime(3610); - let tx = await plotusNewInstance.createMarket(0,1, {gasPrice:100000000000}); + let tx = await plotusNewInstance.createMarket(0,1, {gasPrice:100000000}); eventData = tx.logs[2].args; let gasUsed = eventData.gasUsed.toNumber(); - let gasPrice = 56250000000; + let gasPrice = 56250000; estimatedGasCost = gasPrice*gasUsed; let costInETH = estimatedGasCost; // console.log(gasUsed); @@ -196,13 +197,13 @@ contract("MarketUtility", async function([user1, user2, user3, user4, user5, use }); it("If gas is provided more than 125% of fast gas and maxGas price, reward should be as per minimum of 125% of fast gas or max gasprice", async function() { - await chainlinkGasAgg.setLatestAnswer(125000000000); + await chainlinkGasAgg.setLatestAnswer(125000000); await increaseTime(3610); - let tx = await plotusNewInstance.createMarket(0,1, {gasPrice:150000000000}); + let tx = await plotusNewInstance.createMarket(0,1, {gasPrice:200000000}); eventData = tx.logs[2].args; let gasUsed = eventData.gasUsed.toNumber(); let maxGas = await plotusNewInstance.getUintParameters(toHex("MAXGAS")); - let gasPrice = maxGas[1].toNumber(); + let gasPrice = Math.min(maxGas[1].toNumber(), 125000000*1.25); estimatedGasCost = gasPrice*gasUsed; let costInETH = estimatedGasCost; // console.log(gasUsed); @@ -219,7 +220,7 @@ contract("MarketUtility", async function([user1, user2, user3, user4, user5, use let newBalance = parseFloat(await plotusToken.balanceOf(user1)); // console.log(tx.logs[0].args); // console.log(newBalance); - assert.equal(newBalance/1, oldBalance/1 + incentivesGained); + assert.equal((newBalance/1e18).toFixed(2), (oldBalance/1e18 + incentivesGained/1e18).toFixed(2)); }); }); From 5d22c42b9eb67acf1b3691cc5cf2114889586710 Mon Sep 17 00:00:00 2001 From: udkreddySomish Date: Wed, 21 Oct 2020 12:21:15 +0530 Subject: [PATCH 21/58] Removed redundant checks and corrected indentation --- contracts/MarketRegistryNew.sol | 3 +- contracts/mock/MockChainLinkAggregator.sol | 80 +++++++++++----------- 2 files changed, 42 insertions(+), 41 deletions(-) diff --git a/contracts/MarketRegistryNew.sol b/contracts/MarketRegistryNew.sol index 6aeb98c3..ae41f5d0 100644 --- a/contracts/MarketRegistryNew.sol +++ b/contracts/MarketRegistryNew.sol @@ -95,10 +95,9 @@ contract MarketRegistryNew is MarketRegistry { function claimCreationRewardV2() external { uint256 pendingPLOTReward = userIncentives[msg.sender]; require(pendingPLOTReward > 0); - require(plotToken.balanceOf(address(this)) > pendingPLOTReward); + delete userIncentives[msg.sender]; _transferAsset(address(plotToken), msg.sender, pendingPLOTReward); emit ClaimedMarketCreationReward(msg.sender, pendingPLOTReward); - delete userIncentives[msg.sender]; } /** diff --git a/contracts/mock/MockChainLinkAggregator.sol b/contracts/mock/MockChainLinkAggregator.sol index c187d5bc..58fe7870 100644 --- a/contracts/mock/MockChainLinkAggregator.sol +++ b/contracts/mock/MockChainLinkAggregator.sol @@ -3,49 +3,49 @@ pragma solidity 0.5.7; import "../interfaces/IChainLinkOracle.sol"; contract MockChainLinkAggregator is IChainLinkOracle{ - int256 latestAns = 934999802346; - uint256 updatedAt = now; + int256 latestAns = 934999802346; + uint256 updatedAt = now; - struct RoundData { - uint80 roundId; - int256 answer; - uint256 startedAt; - uint256 updatedAt; - uint80 answeredInRound; - } + struct RoundData { + uint80 roundId; + int256 answer; + uint256 startedAt; + uint256 updatedAt; + uint80 answeredInRound; + } - mapping(uint80 => RoundData) public roundData; - uint80 public currentRound; + mapping(uint80 => RoundData) public roundData; + uint80 public currentRound; - constructor() public { - currentRound = 0; - roundData[0] = RoundData(uint80(0),latestAns, updatedAt, updatedAt, uint80(0)); - } + constructor() public { + currentRound = 0; + roundData[0] = RoundData(uint80(0),latestAns, updatedAt, updatedAt, uint80(0)); + } function decimals() external view returns (uint8) { return uint8(8); } - /** - * @dev Gets the latest answer of chainLink oracle. - * @return int256 representing the latest answer of chainLink oracle. - */ - function latestAnswer() external view returns (int256) - { - return roundData[currentRound].answer; - } + /** + * @dev Gets the latest answer of chainLink oracle. + * @return int256 representing the latest answer of chainLink oracle. + */ + function latestAnswer() external view returns (int256) + { + return roundData[currentRound].answer; + } /** - * @dev Set the latest answer of chainLink oracle. - * @param _latestAnswer The latest anser of chainLink oracle. - */ - function setLatestAnswer(int256 _latestAnswer) public - { + * @dev Set the latest answer of chainLink oracle. + * @param _latestAnswer The latest anser of chainLink oracle. + */ + function setLatestAnswer(int256 _latestAnswer) public + { currentRound = currentRound + uint80(1); roundData[currentRound] = RoundData(currentRound,_latestAnswer, now, now, currentRound); - } + } - function getRoundData(uint80 _roundId) + function getRoundData(uint80 _roundId) external view returns ( @@ -54,12 +54,13 @@ contract MockChainLinkAggregator is IChainLinkOracle{ uint256 startedAt, uint256 updatedAt, uint80 answeredInRound - ) { - return (roundData[_roundId].roundId, roundData[_roundId].answer, roundData[_roundId].startedAt, - roundData[_roundId].updatedAt,roundData[_roundId].answeredInRound); - } + ) + { + return (roundData[_roundId].roundId, roundData[_roundId].answer, roundData[_roundId].startedAt, + roundData[_roundId].updatedAt,roundData[_roundId].answeredInRound); + } - function latestRoundData() + function latestRoundData() external view returns ( @@ -68,9 +69,10 @@ contract MockChainLinkAggregator is IChainLinkOracle{ uint256 startedAt, uint256 updatedAt, uint80 answeredInRound - ) { - return (roundData[currentRound].roundId, roundData[currentRound].answer, roundData[currentRound].startedAt, - roundData[currentRound].updatedAt,roundData[currentRound].answeredInRound); - } + ) + { + return (roundData[currentRound].roundId, roundData[currentRound].answer, roundData[currentRound].startedAt, + roundData[currentRound].updatedAt,roundData[currentRound].answeredInRound); + } } \ No newline at end of file From ae4a1763526419de3ea6876a163be04021b7c936 Mon Sep 17 00:00:00 2001 From: udkreddySomish Date: Wed, 21 Oct 2020 12:21:45 +0530 Subject: [PATCH 22/58] Covergae: Fixed issue with low balance while running coverage --- .solcover.js | 2 +- test/24_UpgradedCreationIncentive.test.js | 72 +++++++++++++++++++---- 2 files changed, 63 insertions(+), 11 deletions(-) diff --git a/.solcover.js b/.solcover.js index 588b29c6..58941407 100644 --- a/.solcover.js +++ b/.solcover.js @@ -1,7 +1,7 @@ module.exports = { skipFiles: ['external', 'mock', 'interfaces', 'marketImplementations'], providerOptions: { - default_balance_ether: 5000, // Extra zero, coverage consumes more gas + default_balance_ether: 110, // Extra zero, coverage consumes more gas network_id: 5777, mnemonic: 'grocery obvious wire insane limit weather parade parrot patrol stock blast ivory', diff --git a/test/24_UpgradedCreationIncentive.test.js b/test/24_UpgradedCreationIncentive.test.js index a8f65213..218db92a 100644 --- a/test/24_UpgradedCreationIncentive.test.js +++ b/test/24_UpgradedCreationIncentive.test.js @@ -63,6 +63,45 @@ contract("MarketUtility", async function([user1, user2, user3, user4, user5, use await marketConfig.setWeth(weth.address); }); + async function updateParameter( + cId, + mrSequence, + code, + contractInst, + type, + proposedValue + ) { + code = toHex(code); + let getterFunction; + if (type == 'uint') { + action = 'updateUintParameters(bytes8,uint)'; + getterFunction = 'getUintParameters'; + } else if (type == 'configAddress') { + action = 'updateConfigAddressParameters(bytes8,address)'; + getterFunction = ''; + } else if (type == 'configUint') { + action = 'updateConfigUintParameters(bytes8,uint256)'; + getterFunction = ''; + } + + let actionHash = encode(action, code, proposedValue); + await gvProposal(cId, actionHash, memberRoles, governance, mrSequence, 0); + if (code == toHex('MASTADD')) { + let newMaster = await NXMaster.at(proposedValue); + contractInst = newMaster; + } + let parameter; + if(type == 'uint') { + parameter = await contractInst[getterFunction](code); + } + try { + parameter[1] = parameter[1].toNumber(); + } catch (err) {} + if(type == 'uint') { + assert.equal(parameter[1], proposedValue, 'Not updated'); + } + } + it('Should Update Existing Market utility Implementation', async function() { let newUtility = await MarketUtility.new(); let existingMarkets = await plotusNewInstance.getOpenMarkets(); @@ -143,10 +182,10 @@ contract("MarketUtility", async function([user1, user2, user3, user4, user5, use }); it("Should create Markets", async function() { - await chainlinkGasAgg.setLatestAnswer(45000000); + await chainlinkGasAgg.setLatestAnswer(450000); await mockUniswapV2Pair.sync(); await increaseTime(3610); - let tx = await plotusNewInstance.createMarket(0,1, {gasPrice:30000000}); + let tx = await plotusNewInstance.createMarket(0,1, {gasPrice:300000}); // console.log(tx.receipt.gasUsed); eventData = tx.logs[2].args; }); @@ -154,7 +193,7 @@ contract("MarketUtility", async function([user1, user2, user3, user4, user5, use it("If gas is provided less than fastgas price from oracle, reward should be as per minimum of fast gas and provided gas", async function() { let gasUsed = eventData.gasUsed.toNumber(); let gasPrice = await chainlinkGasAgg.latestAnswer(); - gasPrice = Math.min(30000000, gasPrice); + gasPrice = Math.min(300000, gasPrice); estimatedGasCost = gasPrice*gasUsed; let costInETH = estimatedGasCost; // console.log(gasUsed); @@ -166,10 +205,10 @@ contract("MarketUtility", async function([user1, user2, user3, user4, user5, use it("If gas is provided upto 125% of fast gas, reward should be as per provided gas", async function() { await increaseTime(3610); - let tx = await plotusNewInstance.createMarket(0,1, {gasPrice:50000000}); + let tx = await plotusNewInstance.createMarket(0,1, {gasPrice:500000}); eventData = tx.logs[2].args; let gasUsed = eventData.gasUsed.toNumber(); - let gasPrice = 50000000; + let gasPrice = 500000; estimatedGasCost = gasPrice*gasUsed; let costInETH = estimatedGasCost; // console.log(gasUsed); @@ -182,10 +221,10 @@ contract("MarketUtility", async function([user1, user2, user3, user4, user5, use it("If gas is provided more than 125% of fast gas, reward should be as per 125% fast gas", async function() { await increaseTime(3610); - let tx = await plotusNewInstance.createMarket(0,1, {gasPrice:100000000}); + let tx = await plotusNewInstance.createMarket(0,1, {gasPrice:1000000}); eventData = tx.logs[2].args; let gasUsed = eventData.gasUsed.toNumber(); - let gasPrice = 56250000; + let gasPrice = 562500; estimatedGasCost = gasPrice*gasUsed; let costInETH = estimatedGasCost; // console.log(gasUsed); @@ -196,14 +235,20 @@ contract("MarketUtility", async function([user1, user2, user3, user4, user5, use assert.equal(eventData.plotIncentive/1, worthInPLOT[1]/1) }); + it('Should update MAXGAS variable', async function() { + await updateParameter(20, 2, 'MAXGAS', plotusNewInstance, 'configUint', 5000); + let configData = await plotusNewInstance.getUintParameters(toHex('MAXGAS')); + assert.equal(configData[1], 5000, 'Not updated'); + }); + it("If gas is provided more than 125% of fast gas and maxGas price, reward should be as per minimum of 125% of fast gas or max gasprice", async function() { - await chainlinkGasAgg.setLatestAnswer(125000000); + await chainlinkGasAgg.setLatestAnswer(1250000); await increaseTime(3610); - let tx = await plotusNewInstance.createMarket(0,1, {gasPrice:200000000}); + let tx = await plotusNewInstance.createMarket(0,1, {gasPrice:2000000}); eventData = tx.logs[2].args; let gasUsed = eventData.gasUsed.toNumber(); let maxGas = await plotusNewInstance.getUintParameters(toHex("MAXGAS")); - let gasPrice = Math.min(maxGas[1].toNumber(), 125000000*1.25); + let gasPrice = Math.min(maxGas[1].toNumber(), 1250000*1.25); estimatedGasCost = gasPrice*gasUsed; let costInETH = estimatedGasCost; // console.log(gasUsed); @@ -222,5 +267,12 @@ contract("MarketUtility", async function([user1, user2, user3, user4, user5, use // console.log(newBalance); assert.equal((newBalance/1e18).toFixed(2), (oldBalance/1e18 + incentivesGained/1e18).toFixed(2)); }); + + it('Should update Chainlink gas aggrefgartor address', async function() { + let clAgg = await MockChainLinkGasPriceAgg.new(); + await updateParameter(21, 2, 'GASAGG', plotusNewInstance, 'configAddress', clAgg.address); + let address = await plotusNewInstance.clGasPriceAggregator(); + assert.equal(address, clAgg.address, 'Not updated'); + }); }); From 902cd4f3e3595ab046a887e1798e25906584f404 Mon Sep 17 00:00:00 2001 From: udkreddySomish Date: Wed, 21 Oct 2020 13:06:56 +0530 Subject: [PATCH 23/58] Updated testcases --- test/24_UpgradedCreationIncentive.test.js | 33 ++++++++++++----------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/test/24_UpgradedCreationIncentive.test.js b/test/24_UpgradedCreationIncentive.test.js index 218db92a..a40cf898 100644 --- a/test/24_UpgradedCreationIncentive.test.js +++ b/test/24_UpgradedCreationIncentive.test.js @@ -167,12 +167,12 @@ contract("MarketUtility", async function([user1, user2, user3, user4, user5, use chainlinkGasAgg = await MockChainLinkGasPriceAgg.new(); await assertRevert(plotusNewInstance.setGasPriceAggAndMaxGas(chainlinkGasAgg.address, {from:user2})); await plotusNewInstance.setGasPriceAggAndMaxGas(chainlinkGasAgg.address); + await assertRevert(plotusNewInstance.setGasPriceAggAndMaxGas(chainlinkGasAgg.address, {from:user2})); }); it("Should be able to claim market creation rewards of pre upgrade", async function() { let oldBalance = parseFloat(await plotusToken.balanceOf(user1)); await plotusNewInstance.claimCreationReward(); - // await plotusNewInstance.claimCreationRewardV2(); let newBalance = parseFloat(await plotusToken.balanceOf(user1)); assert.isAbove(newBalance/1,oldBalance/1); }); @@ -186,7 +186,6 @@ contract("MarketUtility", async function([user1, user2, user3, user4, user5, use await mockUniswapV2Pair.sync(); await increaseTime(3610); let tx = await plotusNewInstance.createMarket(0,1, {gasPrice:300000}); - // console.log(tx.receipt.gasUsed); eventData = tx.logs[2].args; }); @@ -196,8 +195,6 @@ contract("MarketUtility", async function([user1, user2, user3, user4, user5, use gasPrice = Math.min(300000, gasPrice); estimatedGasCost = gasPrice*gasUsed; let costInETH = estimatedGasCost; - // console.log(gasUsed); - // console.log(costInETH); let worthInPLOT = await marketConfig.getValueAndMultiplierParameters(ethAddress, costInETH + ""); incentivesGained += eventData.plotIncentive/1; assert.equal(eventData.plotIncentive/1, worthInPLOT[1]/1); @@ -211,9 +208,6 @@ contract("MarketUtility", async function([user1, user2, user3, user4, user5, use let gasPrice = 500000; estimatedGasCost = gasPrice*gasUsed; let costInETH = estimatedGasCost; - // console.log(gasUsed); - // console.log(tx.receipt.gasUsed); - // console.log(costInETH); let worthInPLOT = await marketConfig.getValueAndMultiplierParameters(ethAddress, costInETH + ""); incentivesGained += eventData.plotIncentive/1; assert.equal(eventData.plotIncentive/1, worthInPLOT[1]/1) @@ -227,9 +221,6 @@ contract("MarketUtility", async function([user1, user2, user3, user4, user5, use let gasPrice = 562500; estimatedGasCost = gasPrice*gasUsed; let costInETH = estimatedGasCost; - // console.log(gasUsed); - // console.log(tx.receipt.gasUsed); - // console.log(costInETH); let worthInPLOT = await marketConfig.getValueAndMultiplierParameters(ethAddress, costInETH + ""); incentivesGained += eventData.plotIncentive/1; assert.equal(eventData.plotIncentive/1, worthInPLOT[1]/1) @@ -237,7 +228,9 @@ contract("MarketUtility", async function([user1, user2, user3, user4, user5, use it('Should update MAXGAS variable', async function() { await updateParameter(20, 2, 'MAXGAS', plotusNewInstance, 'configUint', 5000); - let configData = await plotusNewInstance.getUintParameters(toHex('MAXGAS')); + let configData = await plotusNewInstance.getUintParameters(toHex('MAXGAS1')); + assert.equal(configData[1], 0, 'Not updated'); + configData = await plotusNewInstance.getUintParameters(toHex('MAXGAS')); assert.equal(configData[1], 5000, 'Not updated'); }); @@ -251,9 +244,6 @@ contract("MarketUtility", async function([user1, user2, user3, user4, user5, use let gasPrice = Math.min(maxGas[1].toNumber(), 1250000*1.25); estimatedGasCost = gasPrice*gasUsed; let costInETH = estimatedGasCost; - // console.log(gasUsed); - // console.log(tx.receipt.gasUsed); - // console.log(costInETH); let worthInPLOT = await marketConfig.getValueAndMultiplierParameters(ethAddress, costInETH + ""); incentivesGained += eventData.plotIncentive/1; assert.equal(eventData.plotIncentive/1, worthInPLOT[1]/1) @@ -263,8 +253,6 @@ contract("MarketUtility", async function([user1, user2, user3, user4, user5, use let oldBalance = parseFloat(await plotusToken.balanceOf(user1)); let tx = await plotusNewInstance.claimCreationRewardV2(); let newBalance = parseFloat(await plotusToken.balanceOf(user1)); - // console.log(tx.logs[0].args); - // console.log(newBalance); assert.equal((newBalance/1e18).toFixed(2), (oldBalance/1e18 + incentivesGained/1e18).toFixed(2)); }); @@ -274,5 +262,18 @@ contract("MarketUtility", async function([user1, user2, user3, user4, user5, use let address = await plotusNewInstance.clGasPriceAggregator(); assert.equal(address, clAgg.address, 'Not updated'); }); + + it('Should update Token Stake For Dispute', async function() { + await updateParameter(20, 2, 'TSDISP', plotusNewInstance, 'configUint', 26); + let configData = await marketConfig.getDisputeResolutionParams(); + assert.equal(configData, 26, 'Not updated'); + }); + + it('Should update Uniswap Factory', async function() { + let uniswapFactory = await MockUniswapFactory.new(); + await updateParameter(21, 2, 'UNIFAC', plotusNewInstance, 'configAddress', uniswapFactory.address); + let configData = await marketConfig.getFeedAddresses(); + assert.equal(configData, uniswapFactory.address, 'Not updated'); + }); }); From e45297d9a5d339ff6c278bda5fdda611714898b6 Mon Sep 17 00:00:00 2001 From: udkreddySomish Date: Sat, 31 Oct 2020 00:23:04 +0530 Subject: [PATCH 24/58] Added feature to distribute percent of reward pool share for market creators --- contracts/MarketNew.sol | 600 +++++++++++++++++++++++ contracts/MarketRegistryNew.sol | 114 ++++- contracts/interfaces/IMarketRegistry.sol | 4 + 3 files changed, 711 insertions(+), 7 deletions(-) create mode 100644 contracts/MarketNew.sol diff --git a/contracts/MarketNew.sol b/contracts/MarketNew.sol new file mode 100644 index 00000000..8becd2a2 --- /dev/null +++ b/contracts/MarketNew.sol @@ -0,0 +1,600 @@ +/* Copyright (C) 2020 PlotX.io + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see http://www.gnu.org/licenses/ */ + +pragma solidity 0.5.7; + +import "./external/openzeppelin-solidity/math/SafeMath.sol"; +import "./external/proxy/OwnedUpgradeabilityProxy.sol"; +import "./interfaces/IMarketUtility.sol"; +import "./interfaces/IToken.sol"; +import "./interfaces/ITokenController.sol"; +import "./interfaces/IMarketRegistry.sol"; + +contract MarketNew { + using SafeMath for *; + + enum PredictionStatus { + Live, + InSettlement, + Cooling, + InDispute, + Settled + } + + struct option + { + uint predictionPoints; + mapping(address => uint256) assetStaked; + mapping(address => uint256) assetLeveraged; + } + + struct MarketSettleData { + uint64 WinningOption; + uint64 settleTime; + } + + address constant ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE; + address constant marketFeedAddress = 0x5e2aa6b66531142bEAB830c385646F97fa03D80a; + address constant plotToken = 0xa626089A947Eadc8a782293B53fCf42247C71111; + + IMarketRegistry constant marketRegistry = IMarketRegistry(0x65Add15C5Ff3Abc069358AAe842dE13Ce92f3447); + ITokenController constant tokenController = ITokenController(0x3A3d9ca9d9b25AF1fF7eB9d8a1ea9f61B5892Ee9); + IMarketUtility constant marketUtility = IMarketUtility(0xCBc7df3b8C870C5CDE675AaF5Fd823E4209546D2); + + uint8 constant roundOfToNearest = 25; + uint constant totalOptions = 3; + uint constant MAX_LEVERAGE = 5; + uint constant ethCommissionPerc = 10; //with 2 decimals + uint constant plotCommissionPerc = 5; //with 2 decimals + bytes32 public constant marketCurrency = "ETH/USDT"; + + bool internal lockedForDispute; + address internal incentiveToken; + uint internal ethAmountToPool; + uint internal ethCommissionAmount; + uint internal plotCommissionAmount; + uint internal tokenAmountToPool; + uint internal incentiveToDistribute; + uint[] internal rewardToDistribute; + PredictionStatus internal predictionStatus; + + + struct UserData { + bool claimedReward; + bool predictedWithBlot; + bool multiplierApplied; + mapping(uint => uint) predictionPoints; + mapping(address => mapping(uint => uint)) assetStaked; + mapping(address => mapping(uint => uint)) LeverageAsset; + } + + struct MarketData { + uint64 startTime; + uint64 predictionTime; + uint64 neutralMinValue; + uint64 neutralMaxValue; + } + + MarketData public marketData; + MarketSettleData public marketSettleData; + + mapping(address => UserData) internal userData; + + mapping(uint=>option) public optionsAvailable; + + /** + * @dev Initialize the market. + * @param _startTime The time at which market will create. + * @param _predictionTime The time duration of market. + * @param _minValue The minimum value of neutral option range. + * @param _maxValue The maximum value of neutral option range. + */ + function initiate(uint64 _startTime, uint64 _predictionTime, uint64 _minValue, uint64 _maxValue) public payable { + OwnedUpgradeabilityProxy proxy = OwnedUpgradeabilityProxy(address(uint160(address(this)))); + require(msg.sender == proxy.proxyOwner(),"Sender is not proxy owner."); + require(marketData.startTime == 0, "Already initialized"); + require(_startTime.add(_predictionTime) > now); + marketData.startTime = _startTime; + marketData.predictionTime = _predictionTime; + + marketData.neutralMinValue = _minValue; + marketData.neutralMaxValue = _maxValue; + } + + /** + * @dev Place prediction on the available options of the market. + * @param _asset The asset used by user during prediction whether it is plotToken address or in ether. + * @param _predictionStake The amount staked by user at the time of prediction. + * @param _prediction The option on which user placed prediction. + * @param _leverage The leverage opted by user at the time of prediction. + */ + function placePrediction(address _asset, uint256 _predictionStake, uint256 _prediction,uint256 _leverage) public payable { + require(!marketRegistry.marketCreationPaused() && _prediction <= totalOptions && _leverage <= MAX_LEVERAGE); + require(now >= marketData.startTime && now <= marketExpireTime()); + + uint256 _commissionStake; + if(_asset == ETH_ADDRESS) { + require(_predictionStake == msg.value); + _commissionStake = _calculatePercentage(ethCommissionPerc, _predictionStake, 10000); + ethCommissionAmount = ethCommissionAmount.add(_commissionStake); + } else { + require(msg.value == 0); + if (_asset == plotToken){ + tokenController.transferFrom(plotToken, msg.sender, address(this), _predictionStake); + } else { + require(_asset == tokenController.bLOTToken()); + require(_leverage == MAX_LEVERAGE); + require(!userData[msg.sender].predictedWithBlot); + userData[msg.sender].predictedWithBlot = true; + tokenController.swapBLOT(msg.sender, address(this), _predictionStake); + _asset = plotToken; + } + _commissionStake = _calculatePercentage(plotCommissionPerc, _predictionStake, 10000); + plotCommissionAmount = plotCommissionAmount.add(_commissionStake); + } + _commissionStake = _predictionStake.sub(_commissionStake); + + + (uint predictionPoints, bool isMultiplierApplied) = calculatePredictionValue(_prediction, _commissionStake, _leverage, _asset); + if(isMultiplierApplied) { + userData[msg.sender].multiplierApplied = true; + } + require(predictionPoints > 0); + + _storePredictionData(_prediction, _commissionStake, _asset, _leverage, predictionPoints); + marketRegistry.setUserGlobalPredictionData(msg.sender,_predictionStake, predictionPoints, _asset, _prediction, _leverage); + } + + function calculatePredictionValue(uint _prediction, uint _predictionStake, uint _leverage, address _asset) internal view returns(uint predictionPoints, bool isMultiplierApplied) { + uint[] memory params = new uint[](11); + params[0] = _prediction; + params[1] = marketData.neutralMinValue; + params[2] = marketData.neutralMaxValue; + params[3] = marketData.startTime; + params[4] = marketExpireTime(); + (params[5], params[6]) = getTotalAssetsStaked(); + params[7] = optionsAvailable[_prediction].assetStaked[ETH_ADDRESS]; + params[8] = optionsAvailable[_prediction].assetStaked[plotToken]; + params[9] = _predictionStake; + params[10] = _leverage; + bool checkMultiplier; + if(!userData[msg.sender].multiplierApplied) { + checkMultiplier = true; + } + (predictionPoints, isMultiplierApplied) = marketUtility.calculatePredictionValue(params, _asset, msg.sender, marketFeedAddress, checkMultiplier); + + } + + function getTotalAssetsStaked() public view returns(uint256 ethStaked, uint256 plotStaked) { + for(uint256 i = 1; i<= totalOptions;i++) { + ethStaked = ethStaked.add(optionsAvailable[i].assetStaked[ETH_ADDRESS]); + plotStaked = plotStaked.add(optionsAvailable[i].assetStaked[plotToken]); + } + } + + function getTotalStakedValueInPLOT() public view returns(uint256) { + (uint256 ethStaked, uint256 plotStaked) = getTotalAssetsStaked(); + (, ethStaked) = marketUtility.getValueAndMultiplierParameters(ETH_ADDRESS, ethStaked); + return plotStaked.add(ethStaked); + } + + /** + * @dev Stores the prediction data. + * @param _prediction The option on which user place prediction. + * @param _predictionStake The amount staked by user at the time of prediction. + * @param _asset The asset used by user during prediction. + * @param _leverage The leverage opted by user during prediction. + * @param predictionPoints The positions user got during prediction. + */ + function _storePredictionData(uint _prediction, uint _predictionStake, address _asset, uint _leverage, uint predictionPoints) internal { + userData[msg.sender].predictionPoints[_prediction] = userData[msg.sender].predictionPoints[_prediction].add(predictionPoints); + userData[msg.sender].assetStaked[_asset][_prediction] = userData[msg.sender].assetStaked[_asset][_prediction].add(_predictionStake); + userData[msg.sender].LeverageAsset[_asset][_prediction] = userData[msg.sender].LeverageAsset[_asset][_prediction].add(_predictionStake.mul(_leverage)); + optionsAvailable[_prediction].predictionPoints = optionsAvailable[_prediction].predictionPoints.add(predictionPoints); + optionsAvailable[_prediction].assetStaked[_asset] = optionsAvailable[_prediction].assetStaked[_asset].add(_predictionStake); + optionsAvailable[_prediction].assetLeveraged[_asset] = optionsAvailable[_prediction].assetLeveraged[_asset].add(_predictionStake.mul(_leverage)); + } + + /** + * @dev Settle the market, setting the winning option + */ + function settleMarket() external { + (uint256 _value, uint256 _roundId) = marketUtility.getSettlemetPrice(marketFeedAddress, uint256(marketSettleTime())); + if(marketStatus() == PredictionStatus.InSettlement) { + _postResult(_value, _roundId); + } + } + + /** + * @dev Calculate the result of market. + * @param _value The current price of market currency. + */ + function _postResult(uint256 _value, uint256 _roundId) internal { + require(now >= marketSettleTime(),"Time not reached"); + require(_value > 0,"value should be greater than 0"); + uint riskPercentage; + ( , riskPercentage, , ) = marketUtility.getBasicMarketDetails(); + if(predictionStatus != PredictionStatus.InDispute) { + marketSettleData.settleTime = uint64(now); + } else { + delete marketSettleData.settleTime; + } + predictionStatus = PredictionStatus.Settled; + if(_value < marketData.neutralMinValue) { + marketSettleData.WinningOption = 1; + } else if(_value > marketData.neutralMaxValue) { + marketSettleData.WinningOption = 3; + } else { + marketSettleData.WinningOption = 2; + } + (, uint256 rewardPoolSharePerc) = marketRegistry.getUintParameters("RPPERCMC"); + uint[] memory totalReward = new uint256[](2); + uint[] memory marketCreatorIncentive = new uint256[](2); + if(optionsAvailable[marketSettleData.WinningOption].assetStaked[ETH_ADDRESS] > 0 || + optionsAvailable[marketSettleData.WinningOption].assetStaked[plotToken] > 0 + ){ + for(uint i=1;i <= totalOptions;i++){ + if(i!=marketSettleData.WinningOption) { + uint256 leveragedAsset = _calculatePercentage(riskPercentage, optionsAvailable[i].assetLeveraged[plotToken], 100); + totalReward[0] = totalReward[0].add(leveragedAsset); + leveragedAsset = _calculatePercentage(riskPercentage, optionsAvailable[i].assetLeveraged[ETH_ADDRESS], 100); + totalReward[1] = totalReward[1].add(leveragedAsset); + } + } + marketCreatorIncentive[0] = _calculatePercentage(rewardPoolSharePerc, totalReward[0], 100); + marketCreatorIncentive[1] = _calculatePercentage(rewardPoolSharePerc, totalReward[1], 100); + rewardToDistribute[0] = totalReward[0].sub(marketCreatorIncentive[0]); + rewardToDistribute[1] = totalReward[1].sub(marketCreatorIncentive[1]); + // rewardToDistribute = totalReward; + } else { + for(uint i=1;i <= totalOptions;i++){ + uint256 leveragedAsset = _calculatePercentage(riskPercentage, optionsAvailable[i].assetLeveraged[plotToken], 100); + tokenAmountToPool = tokenAmountToPool.add(leveragedAsset); + leveragedAsset = _calculatePercentage(riskPercentage, optionsAvailable[i].assetLeveraged[ETH_ADDRESS], 100); + ethAmountToPool = ethAmountToPool.add(leveragedAsset); + } + } + _transferAsset(ETH_ADDRESS, address(marketRegistry), ethAmountToPool.add(ethCommissionAmount)); + _transferAsset(plotToken, address(marketRegistry), tokenAmountToPool.add(plotCommissionAmount)); + delete ethCommissionAmount; + delete plotCommissionAmount; + marketRegistry.callMarketResultEvent(rewardToDistribute, marketCreatorIncentive, marketSettleData.WinningOption, _value, _roundId); + } + + function _calculatePercentage(uint256 _percent, uint256 _value, uint256 _divisor) internal pure returns(uint256) { + return _percent.mul(_value).div(_divisor); + } + + /** + * @dev Raise the dispute if wrong value passed at the time of market result declaration. + * @param proposedValue The proposed value of market currency. + * @param proposalTitle The title of proposal created by user. + * @param description The description of dispute. + * @param solutionHash The ipfs solution hash. + */ + function raiseDispute(uint256 proposedValue, string memory proposalTitle, string memory description, string memory solutionHash) public { + require(getTotalStakedValueInPLOT() > 0, "No participation"); + require(marketStatus() == PredictionStatus.Cooling); + uint _stakeForDispute = marketUtility.getDisputeResolutionParams(); + tokenController.transferFrom(plotToken, msg.sender, address(marketRegistry), _stakeForDispute); + lockedForDispute = true; + marketRegistry.createGovernanceProposal(proposalTitle, description, solutionHash, abi.encode(address(this), proposedValue), _stakeForDispute, msg.sender, ethAmountToPool, tokenAmountToPool, proposedValue); + delete ethAmountToPool; + delete tokenAmountToPool; + predictionStatus = PredictionStatus.InDispute; + } + + /** + * @dev Resolve the dispute + * @param accepted Flag mentioning if dispute is accepted or not + * @param finalResult The final correct value of market currency. + */ + function resolveDispute(bool accepted, uint256 finalResult) external payable { + require(msg.sender == address(marketRegistry) && marketStatus() == PredictionStatus.InDispute); + if(accepted) { + _postResult(finalResult, 0); + } + lockedForDispute = false; + predictionStatus = PredictionStatus.Settled; + } + + function sponsorIncentives(address _token, uint256 _value) external { + require(marketRegistry.isWhitelistedSponsor(msg.sender)); + require(marketStatus() <= PredictionStatus.InSettlement); + require(incentiveToken == address(0), "Already sponsored"); + incentiveToken = _token; + incentiveToDistribute = _value; + tokenController.transferFrom(_token, msg.sender, address(this), _value); + } + + + /** + * @dev Claim the return amount of the specified address. + * @param _user The address to query the claim return amount of. + * @return Flag, if 0:cannot claim, 1: Already Claimed, 2: Claimed + */ + function claimReturn(address payable _user) public returns(uint256) { + + if(lockedForDispute || marketStatus() != PredictionStatus.Settled || marketRegistry.marketCreationPaused()) { + return 0; + } + if(userData[_user].claimedReward) { + return 1; + } + userData[_user].claimedReward = true; + (uint[] memory _returnAmount, address[] memory _predictionAssets, uint _incentive, ) = getReturn(_user); + _transferAsset(plotToken, _user, _returnAmount[0]); + _transferAsset(ETH_ADDRESS, _user, _returnAmount[1]); + _transferAsset(incentiveToken, _user, _incentive); + marketRegistry.callClaimedEvent(_user, _returnAmount, _predictionAssets, _incentive, incentiveToken); + return 2; + } + + /** + * @dev Transfer the assets to specified address. + * @param _asset The asset transfer to the specific address. + * @param _recipient The address to transfer the asset of + * @param _amount The amount which is transfer. + */ + function _transferAsset(address _asset, address payable _recipient, uint256 _amount) internal { + if(_amount > 0) { + if(_asset == ETH_ADDRESS) { + _recipient.transfer(_amount); + } else { + require(IToken(_asset).transfer(_recipient, _amount)); + } + } + } + + /** + * @dev Get market settle time + * @return the time at which the market result will be declared + */ + function marketSettleTime() public view returns(uint64) { + if(marketSettleData.settleTime > 0) { + return marketSettleData.settleTime; + } + return uint64(marketData.startTime.add(marketData.predictionTime.mul(2))); + } + + /** + * @dev Get market expire time + * @return the time upto which user can place predictions in market + */ + function marketExpireTime() internal view returns(uint256) { + return marketData.startTime.add(marketData.predictionTime); + } + + /** + * @dev Get market cooldown time + * @return the time upto which user can raise the dispute after the market is settled + */ + function marketCoolDownTime() public view returns(uint256) { + return marketSettleData.settleTime.add(marketData.predictionTime.div(4)); + } + + /** + * @dev Get market Feed data + * @return market currency name + * @return market currency feed address + */ + function getMarketFeedData() public view returns(uint8, bytes32, address) { + return (roundOfToNearest, marketCurrency, marketFeedAddress); + } + + /** + * @dev Get estimated amount of prediction points for given inputs. + * @param _prediction The option on which user place prediction. + * @param _stakeValueInEth The amount staked by user. + * @param _leverage The leverage opted by user at the time of prediction. + * @return uint256 representing the prediction points. + */ + function estimatePredictionValue(uint _prediction, uint _stakeValueInEth, uint _leverage) public view returns(uint _predictionValue){ + (_predictionValue, ) = calculatePredictionValue(_prediction, _stakeValueInEth, _leverage, ETH_ADDRESS); + } + + /** + * @dev Gets the price of specific option. + * @param _prediction The option number to query the balance of. + * @return Price of the option. + */ + function getOptionPrice(uint _prediction) public view returns(uint) { + uint[] memory params = new uint[](9); + params[0] = _prediction; + params[1] = marketData.neutralMinValue; + params[2] = marketData.neutralMaxValue; + params[3] = marketData.startTime; + params[4] = marketExpireTime(); + (params[5], params[6]) = getTotalAssetsStaked(); + params[7] = optionsAvailable[_prediction].assetStaked[ETH_ADDRESS]; + params[8] = optionsAvailable[_prediction].assetStaked[plotToken]; + return marketUtility.calculateOptionPrice(params, marketFeedAddress); + } + + /** + * @dev Gets number of positions user got in prediction + * @param _user Address of user + * @param _option Option Id + */ + function getUserPredictionPoints(address _user, uint256 _option) external view returns(uint256) { + return userData[_user].predictionPoints[_option]; + } + + /** + * @dev Gets the market data. + * @return _marketCurrency bytes32 representing the currency or stock name of the market. + * @return minvalue uint[] memory representing the minimum range of all the options of the market. + * @return maxvalue uint[] memory representing the maximum range of all the options of the market. + * @return _optionPrice uint[] memory representing the option price of each option ranges of the market. + * @return _ethStaked uint[] memory representing the ether staked on each option ranges of the market. + * @return _plotStaked uint[] memory representing the plot staked on each option ranges of the market. + * @return _predictionTime uint representing the type of market. + * @return _expireTime uint representing the time at which market closes for prediction + * @return _predictionStatus uint representing the status of the market. + */ + function getData() public view returns + (bytes32 _marketCurrency,uint[] memory minvalue,uint[] memory maxvalue, + uint[] memory _optionPrice, uint[] memory _ethStaked, uint[] memory _plotStaked,uint _predictionTime,uint _expireTime, uint _predictionStatus){ + _marketCurrency = marketCurrency; + _predictionTime = marketData.predictionTime; + _expireTime =marketExpireTime(); + _predictionStatus = uint(marketStatus()); + minvalue = new uint[](totalOptions); + minvalue[1] = marketData.neutralMinValue; + minvalue[2] = marketData.neutralMaxValue.add(1); + maxvalue = new uint[](totalOptions); + maxvalue[0] = marketData.neutralMinValue.sub(1); + maxvalue[1] = marketData.neutralMaxValue; + maxvalue[2] = ~uint256(0); + + _optionPrice = new uint[](totalOptions); + _ethStaked = new uint[](totalOptions); + _plotStaked = new uint[](totalOptions); + for (uint i = 0; i < totalOptions; i++) { + _ethStaked[i] = optionsAvailable[i+1].assetStaked[ETH_ADDRESS]; + _plotStaked[i] = optionsAvailable[i+1].assetStaked[plotToken]; + _optionPrice[i] = getOptionPrice(i+1); + } + } + + /** + * @dev Gets the result of the market. + * @return uint256 representing the winning option of the market. + * @return uint256 Value of market currently at the time closing market. + * @return uint256 representing the positions of the winning option. + * @return uint[] memory representing the reward to be distributed. + * @return uint256 representing the Eth staked on winning option. + * @return uint256 representing the PLOT staked on winning option. + */ + function getMarketResults() public view returns(uint256, uint256, uint256[] memory, uint256, uint256) { + return (marketSettleData.WinningOption, optionsAvailable[marketSettleData.WinningOption].predictionPoints, rewardToDistribute, optionsAvailable[marketSettleData.WinningOption].assetStaked[ETH_ADDRESS], optionsAvailable[marketSettleData.WinningOption].assetStaked[plotToken]); + } + + + /** + * @dev Gets the return amount of the specified address. + * @param _user The address to specify the return of + * @return returnAmount uint[] memory representing the return amount. + * @return incentive uint[] memory representing the amount incentive. + * @return _incentiveTokens address[] memory representing the incentive tokens. + */ + function getReturn(address _user)public view returns (uint[] memory returnAmount, address[] memory _predictionAssets, uint incentive, address _incentiveToken){ + (uint256 ethStaked, uint256 plotStaked) = getTotalAssetsStaked(); + if(marketStatus() != PredictionStatus.Settled || ethStaked.add(plotStaked) ==0) { + return (returnAmount, _predictionAssets, incentive, incentiveToken); + } + _predictionAssets = new address[](2); + _predictionAssets[0] = plotToken; + _predictionAssets[1] = ETH_ADDRESS; + + uint256 _totalUserPredictionPoints = 0; + uint256 _totalPredictionPoints = 0; + (returnAmount, _totalUserPredictionPoints, _totalPredictionPoints) = _calculateUserReturn(_user); + incentive = _calculateIncentives(_totalUserPredictionPoints, _totalPredictionPoints); + if(userData[_user].predictionPoints[marketSettleData.WinningOption] > 0) { + returnAmount = _addUserReward(_user, returnAmount); + } + return (returnAmount, _predictionAssets, incentive, incentiveToken); + } + + /** + * @dev Get flags set for user + * @param _user User address + * @return Flag defining if user had availed multiplier + * @return Flag defining if user had predicted with bPLOT + */ + function getUserFlags(address _user) external view returns(bool, bool) { + return (userData[_user].multiplierApplied, userData[_user].predictedWithBlot); + } + + /** + * @dev Adds the reward in the total return of the specified address. + * @param _user The address to specify the return of. + * @param returnAmount The return amount. + * @return uint[] memory representing the return amount after adding reward. + */ + function _addUserReward(address _user, uint[] memory returnAmount) internal view returns(uint[] memory){ + uint reward; + for(uint j = 0; j< returnAmount.length; j++) { + reward = userData[_user].predictionPoints[marketSettleData.WinningOption].mul(rewardToDistribute[j]).div(optionsAvailable[marketSettleData.WinningOption].predictionPoints); + returnAmount[j] = returnAmount[j].add(reward); + } + return returnAmount; + } + + /** + * @dev Calculate the return of the specified address. + * @param _user The address to query the return of. + * @return _return uint[] memory representing the return amount owned by the passed address. + * @return _totalUserPredictionPoints uint representing the positions owned by the passed address. + * @return _totalPredictionPoints uint representing the total positions of winners. + */ + function _calculateUserReturn(address _user) internal view returns(uint[] memory _return, uint _totalUserPredictionPoints, uint _totalPredictionPoints){ + ( , uint riskPercentage, , ) = marketUtility.getBasicMarketDetails(); + _return = new uint256[](2); + for(uint i=1;i<=totalOptions;i++){ + _totalUserPredictionPoints = _totalUserPredictionPoints.add(userData[_user].predictionPoints[i]); + _totalPredictionPoints = _totalPredictionPoints.add(optionsAvailable[i].predictionPoints); + _return[0] = _callReturn(_return[0], _user, i, riskPercentage, plotToken); + _return[1] = _callReturn(_return[1], _user, i, riskPercentage, ETH_ADDRESS); + } + } + + /** + * @dev Calculates the incentives. + * @param _totalUserPredictionPoints The positions of user. + * @param _totalPredictionPoints The total positions of winners. + * @return incentive the calculated incentive. + */ + function _calculateIncentives(uint256 _totalUserPredictionPoints, uint256 _totalPredictionPoints) internal view returns(uint256 incentive){ + incentive = _totalUserPredictionPoints.mul(incentiveToDistribute.div(_totalPredictionPoints)); + } + + // /** + // * @dev Gets the pending return. + // * @param _user The address to specify the return of. + // * @return uint representing the pending return amount. + // */ + // function getPendingReturn(address _user) external view returns(uint[] memory returnAmount, address[] memory _predictionAssets, uint[] memory incentive, address[] memory _incentiveTokens){ + // if(userClaimedReward[_user]) return (0,0); + // return getReturn(_user); + // } + + /** + * @dev Calls the total return amount internally. + */ + function _callReturn(uint _return,address _user,uint i,uint riskPercentage, address _asset)internal view returns(uint){ + if(i == marketSettleData.WinningOption) { + riskPercentage = 0; + } + uint256 leveragedAsset = _calculatePercentage(riskPercentage, userData[_user].LeverageAsset[_asset][i], 100); + return _return.add(userData[_user].assetStaked[_asset][i].sub(leveragedAsset)); + } + + + /** + * @dev Gets the status of market. + * @return PredictionStatus representing the status of market. + */ + function marketStatus() internal view returns(PredictionStatus){ + if(predictionStatus == PredictionStatus.Live && now >= marketExpireTime()) { + return PredictionStatus.InSettlement; + } else if(predictionStatus == PredictionStatus.Settled && now <= marketCoolDownTime()) { + return PredictionStatus.Cooling; + } + return predictionStatus; + } + +} diff --git a/contracts/MarketRegistryNew.sol b/contracts/MarketRegistryNew.sol index ae41f5d0..aadd1958 100644 --- a/contracts/MarketRegistryNew.sol +++ b/contracts/MarketRegistryNew.sol @@ -17,13 +17,29 @@ pragma solidity 0.5.7; import "./MarketRegistry.sol"; import "./interfaces/IChainLinkOracle.sol"; import "./external/openzeppelin-solidity/math/Math.sol"; +import "./interfaces/ITokenController.sol"; contract MarketRegistryNew is MarketRegistry { uint256 internal maxGasPrice; IChainLinkOracle public clGasPriceAggregator; + struct MarketCreationRewardUserData { + uint incentives; + uint lastClaimedIndex; + address[] marketsCreated; + } + + struct MarketCreationRewardData { + uint ethIncentive; + uint plotIncentive; + bool rewardPoolShareApplicable; + } - mapping(address => uint256) userIncentives; + uint256 public rewardPoolPercForMC; + uint256 public plotStakeForRewardPoolShare; + + mapping(address => MarketCreationRewardUserData) private marketCreationRewardUserData; //Of user + mapping(address => MarketCreationRewardData) private marketCreationRewardData; //Of user event MarketCreationReward(address indexed createdBy, uint256 plotIncentive, uint256 gasUsed, uint256 gasCost, uint256 gasPriceConsidered, uint256 gasPriceGiven, uint256 maxGasCap); event ClaimedMarketCreationReward(address indexed user, uint256 plotIncentive); @@ -62,23 +78,34 @@ contract MarketRegistryNew is MarketRegistry { uint64 _minValue = uint64((ceil(currentPrice.sub(_optionRangePerc).div(_roundOfToNearest), 10**_decimals)).mul(_roundOfToNearest)); uint64 _maxValue = uint64((ceil(currentPrice.add(_optionRangePerc).div(_roundOfToNearest), 10**_decimals)).mul(_roundOfToNearest)); _createMarket(_marketType, _marketCurrencyIndex, _minValue, _maxValue, _marketStartTime, _currencyName); + _checkIfCreatorStaked(marketCreationData[_marketType][_marketCurrencyIndex].marketAddress); uint256 gasUsed = gasProvided - gasleft(); - _calculateIncentive(gasUsed); + _calculateIncentive(gasUsed, marketCreationData[_marketType][_marketCurrencyIndex].marketAddress); } /** * @dev internal function to calculate user incentive for market creation */ - function _calculateIncentive(uint256 gasUsed) internal{ + function _calculateIncentive(uint256 gasUsed, address _marketAddress) internal{ //Adding buffer gas for below calculations gasUsed = gasUsed + 38500; uint256 gasPrice = _checkGasPrice(); uint256 gasCost = gasUsed.mul(gasPrice); (, uint256 incentive) = marketUtility.getValueAndMultiplierParameters(ETH_ADDRESS, gasCost); - userIncentives[msg.sender] = userIncentives[msg.sender].add(incentive); + marketCreationRewardUserData[msg.sender].incentives = marketCreationRewardUserData[msg.sender].incentives.add(incentive); + marketCreationRewardUserData[msg.sender].marketsCreated.push(_marketAddress); emit MarketCreationReward(msg.sender, incentive, gasUsed, gasCost, gasPrice, tx.gasprice, maxGasPrice); } + function _checkIfCreatorStaked(address _market) internal { + if( + ITokenController(tokenController).tokensLockedAtTime(msg.sender, "SM", now) + >= plotStakeForRewardPoolShare) + { + marketCreationRewardData[_market].rewardPoolShareApplicable = true; + } + } + /** * @dev internal function to calculate gas price for market creation incentives */ @@ -88,18 +115,83 @@ contract MarketRegistryNew is MarketRegistry { return Math.min(Math.min(tx.gasprice,fastGasWithMaxDeviation), maxGasPrice); } + /** + * @dev Resolve the dispute if wrong value passed at the time of market result declaration. + * @param _marketAddress The address specify the market. + * @param _result The final result of the market. + */ + function resolveDispute(address payable _marketAddress, uint256 _result) external onlyAuthorizedToGovern { + uint256 ethDepositedInPool = marketData[_marketAddress].disputeStakes.ethDeposited; + uint256 plotDepositedInPool = marketData[_marketAddress].disputeStakes.tokenDeposited; + uint256 stakedAmount = marketData[_marketAddress].disputeStakes.stakeAmount; + address payable staker = address(uint160(marketData[_marketAddress].disputeStakes.staker)); + address plotTokenAddress = address(plotToken); + plotDepositedInPool = plotDepositedInPool.add(marketCreationRewardData[_marketAddress].plotIncentive); + ethDepositedInPool = ethDepositedInPool.add(marketCreationRewardData[_marketAddress].ethIncentive); + delete marketCreationRewardData[_marketAddress].plotIncentive; + delete marketCreationRewardData[_marketAddress].ethIncentive; + _transferAsset(plotTokenAddress, _marketAddress, plotDepositedInPool); + IMarket(_marketAddress).resolveDispute.value(ethDepositedInPool)(true, _result); + emit DisputeResolved(_marketAddress, true); + _transferAsset(plotTokenAddress, staker, stakedAmount); + } /** * @dev function to reward user for initiating market creation calls as per the new incetive calculations */ - function claimCreationRewardV2() external { - uint256 pendingPLOTReward = userIncentives[msg.sender]; + function claimCreationRewardV2(uint256 _maxRecords) external { + uint256 pendingPLOTReward = marketCreationRewardUserData[msg.sender].incentives; require(pendingPLOTReward > 0); - delete userIncentives[msg.sender]; + delete marketCreationRewardUserData[msg.sender].incentives; + _getRewardPoolIncentives(_maxRecords); _transferAsset(address(plotToken), msg.sender, pendingPLOTReward); emit ClaimedMarketCreationReward(msg.sender, pendingPLOTReward); } + function _getRewardPoolIncentives(uint256 _maxRecords) internal { + MarketCreationRewardUserData storage rewardData = marketCreationRewardUserData[msg.sender]; + uint256 len = rewardData.marketsCreated.length; + uint lastClaimed = len; + uint256 count; + uint256 i; + uint256 ethIncentive; + uint256 plotIncentive; + for(i = rewardData.lastClaimedIndex;i < len && count < _maxRecords; i++) { + MarketCreationRewardData memory marketData = marketCreationRewardData[rewardData.marketsCreated[i]]; + if(marketData.rewardPoolShareApplicable) + { + ( , , , , , , , , uint _predictionStatus) = IMarket(rewardData.marketsCreated[i]).getData(); + if(_predictionStatus == uint(IMarket.PredictionStatus.Settled)) { + ethIncentive = ethIncentive.add(marketData.ethIncentive); + plotIncentive = plotIncentive.add(marketData.plotIncentive); + count++; + } else { + if(lastClaimed == len && (marketData.plotIncentive > 0 || marketData.ethIncentive > 0)) { + lastClaimed = i; + } + } + } + } + if(lastClaimed == len) { + lastClaimed = i; + } + rewardData.lastClaimedIndex = lastClaimed; + } + + /** + * @dev Emits the MarketResult event. + * @param _totalReward The amount of reward to be distribute. + * @param winningOption The winning option of the market. + * @param closeValue The closing value of the market currency. + */ + function callMarketResultEvent(uint256[] calldata _totalReward, uint256[] calldata marketCreatorIncentive, uint256 winningOption, uint256 closeValue, uint _roundId) external { + require(isMarket(msg.sender)); + marketCreationRewardData[msg.sender].plotIncentive = marketCreatorIncentive[0]; + marketCreationRewardData[msg.sender].ethIncentive = marketCreatorIncentive[1]; + emit MarketResult(msg.sender, _totalReward, winningOption, closeValue, _roundId); + } + + /** * @dev function to update address parameters of market */ @@ -119,6 +211,10 @@ contract MarketRegistryNew is MarketRegistry { marketCreationIncentive = value; } else if(code == "MAXGAS") { // Maximum gas upto which is considered while calculating market creation incentives maxGasPrice = value; + } else if(code == "RPPERCMC") { // Reward Pool percent for market creator + rewardPoolPercForMC = value; + } else if(code == "PSFRPS") { // Reward Pool percent for market creator + plotStakeForRewardPoolShare = value; } else { marketUtility.updateUintParameters(code, value); } @@ -133,6 +229,10 @@ contract MarketRegistryNew is MarketRegistry { value = marketCreationIncentive; } else if(code == "MAXGAS") { value = maxGasPrice; + } else if(code == "RPPERCMC") { + value = rewardPoolPercForMC; + } else if(code == "PSFRPS") { + value = plotStakeForRewardPoolShare; } } diff --git a/contracts/interfaces/IMarketRegistry.sol b/contracts/interfaces/IMarketRegistry.sol index 99f1ad0b..e31c4d2b 100644 --- a/contracts/interfaces/IMarketRegistry.sol +++ b/contracts/interfaces/IMarketRegistry.sol @@ -23,6 +23,10 @@ contract IMarketRegistry { function transferAssets(address _asset, address _to, uint _amount) external; + function callMarketResultEvent(uint256[] calldata _totalReward, uint256[] calldata marketCreatorIncentive, uint256 winningOption, uint256 closeValue, uint _roundId) external; + + function getUintParameters(bytes8 code) external view returns(bytes8 codeVal, uint256 value); + /** * @dev Initialize the PlotX. * @param _marketConfig The address of market config. From 084863a971a88083bc9d8626c52200e63280b470 Mon Sep 17 00:00:00 2001 From: udkreddySomish Date: Sat, 31 Oct 2020 10:13:39 +0530 Subject: [PATCH 25/58] Fixed compile issues --- contracts/MarketRegistryNew.sol | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/contracts/MarketRegistryNew.sol b/contracts/MarketRegistryNew.sol index aadd1958..2c44d916 100644 --- a/contracts/MarketRegistryNew.sol +++ b/contracts/MarketRegistryNew.sol @@ -79,21 +79,21 @@ contract MarketRegistryNew is MarketRegistry { uint64 _maxValue = uint64((ceil(currentPrice.add(_optionRangePerc).div(_roundOfToNearest), 10**_decimals)).mul(_roundOfToNearest)); _createMarket(_marketType, _marketCurrencyIndex, _minValue, _maxValue, _marketStartTime, _currencyName); _checkIfCreatorStaked(marketCreationData[_marketType][_marketCurrencyIndex].marketAddress); + marketCreationRewardUserData[msg.sender].marketsCreated.push(marketCreationData[_marketType][_marketCurrencyIndex].marketAddress); uint256 gasUsed = gasProvided - gasleft(); - _calculateIncentive(gasUsed, marketCreationData[_marketType][_marketCurrencyIndex].marketAddress); + _calculateIncentive(gasUsed); } /** * @dev internal function to calculate user incentive for market creation */ - function _calculateIncentive(uint256 gasUsed, address _marketAddress) internal{ + function _calculateIncentive(uint256 gasUsed) internal{ //Adding buffer gas for below calculations gasUsed = gasUsed + 38500; uint256 gasPrice = _checkGasPrice(); uint256 gasCost = gasUsed.mul(gasPrice); (, uint256 incentive) = marketUtility.getValueAndMultiplierParameters(ETH_ADDRESS, gasCost); marketCreationRewardUserData[msg.sender].incentives = marketCreationRewardUserData[msg.sender].incentives.add(incentive); - marketCreationRewardUserData[msg.sender].marketsCreated.push(_marketAddress); emit MarketCreationReward(msg.sender, incentive, gasUsed, gasCost, gasPrice, tx.gasprice, maxGasPrice); } From 41ab257f50059b46932496c3ded47bd4fa4e8445 Mon Sep 17 00:00:00 2001 From: udkreddySomish Date: Sat, 31 Oct 2020 10:20:37 +0530 Subject: [PATCH 26/58] Corrected event while claimingmarket creation incentives --- contracts/MarketRegistryNew.sol | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/contracts/MarketRegistryNew.sol b/contracts/MarketRegistryNew.sol index 2c44d916..af86178b 100644 --- a/contracts/MarketRegistryNew.sol +++ b/contracts/MarketRegistryNew.sol @@ -41,7 +41,7 @@ contract MarketRegistryNew is MarketRegistry { mapping(address => MarketCreationRewardUserData) private marketCreationRewardUserData; //Of user mapping(address => MarketCreationRewardData) private marketCreationRewardData; //Of user event MarketCreationReward(address indexed createdBy, uint256 plotIncentive, uint256 gasUsed, uint256 gasCost, uint256 gasPriceConsidered, uint256 gasPriceGiven, uint256 maxGasCap); - event ClaimedMarketCreationReward(address indexed user, uint256 plotIncentive); + event ClaimedMarketCreationReward(address indexed user, uint256 ethIncentive, uint256 plotIncentive); /** * @dev Set initial market creation incentive params. @@ -143,19 +143,19 @@ contract MarketRegistryNew is MarketRegistry { uint256 pendingPLOTReward = marketCreationRewardUserData[msg.sender].incentives; require(pendingPLOTReward > 0); delete marketCreationRewardUserData[msg.sender].incentives; - _getRewardPoolIncentives(_maxRecords); + (uint256 ethIncentive, uint256 plotIncentive) = _getRewardPoolIncentives(_maxRecords); + pendingPLOTReward = pendingPLOTReward.add(plotIncentive); _transferAsset(address(plotToken), msg.sender, pendingPLOTReward); - emit ClaimedMarketCreationReward(msg.sender, pendingPLOTReward); + _transferAsset(ETH_ADDRESS, msg.sender, ethIncentive); + emit ClaimedMarketCreationReward(msg.sender, ethIncentive, pendingPLOTReward); } - function _getRewardPoolIncentives(uint256 _maxRecords) internal { + function _getRewardPoolIncentives(uint256 _maxRecords) internal returns(uint256 ethIncentive, uint256 plotIncentive) { MarketCreationRewardUserData storage rewardData = marketCreationRewardUserData[msg.sender]; uint256 len = rewardData.marketsCreated.length; uint lastClaimed = len; uint256 count; uint256 i; - uint256 ethIncentive; - uint256 plotIncentive; for(i = rewardData.lastClaimedIndex;i < len && count < _maxRecords; i++) { MarketCreationRewardData memory marketData = marketCreationRewardData[rewardData.marketsCreated[i]]; if(marketData.rewardPoolShareApplicable) From 64c01e12baa3df285e2d5303f2eb85020319e212 Mon Sep 17 00:00:00 2001 From: udkreddySomish Date: Sat, 31 Oct 2020 10:34:59 +0530 Subject: [PATCH 27/58] Corrected formulae --- contracts/MarketNew.sol | 2 +- contracts/MarketRegistryNew.sol | 18 ++++++++++++++---- contracts/interfaces/IMarketRegistry.sol | 2 ++ 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/contracts/MarketNew.sol b/contracts/MarketNew.sol index 8becd2a2..60e59993 100644 --- a/contracts/MarketNew.sol +++ b/contracts/MarketNew.sol @@ -239,7 +239,7 @@ contract MarketNew { } else { marketSettleData.WinningOption = 2; } - (, uint256 rewardPoolSharePerc) = marketRegistry.getUintParameters("RPPERCMC"); + uint256 rewardPoolSharePerc = marketRegistry.getMarketCreatorRPoolSharePerc(address(this)); uint[] memory totalReward = new uint256[](2); uint[] memory marketCreatorIncentive = new uint256[](2); if(optionsAvailable[marketSettleData.WinningOption].assetStaked[ETH_ADDRESS] > 0 || diff --git a/contracts/MarketRegistryNew.sol b/contracts/MarketRegistryNew.sol index af86178b..8df3d38d 100644 --- a/contracts/MarketRegistryNew.sol +++ b/contracts/MarketRegistryNew.sol @@ -32,11 +32,12 @@ contract MarketRegistryNew is MarketRegistry { struct MarketCreationRewardData { uint ethIncentive; uint plotIncentive; + uint8 rewardPoolSharePerc; bool rewardPoolShareApplicable; } - uint256 public rewardPoolPercForMC; - uint256 public plotStakeForRewardPoolShare; + uint256 rewardPoolPercForMC; + uint256 plotStakeForRewardPoolShare; mapping(address => MarketCreationRewardUserData) private marketCreationRewardUserData; //Of user mapping(address => MarketCreationRewardData) private marketCreationRewardData; //Of user @@ -51,6 +52,8 @@ contract MarketRegistryNew is MarketRegistry { require(msg.sender == marketInitiater); clGasPriceAggregator = IChainLinkOracle(_clGasPriceAggregator); maxGasPrice = 100 * 10**9; + rewardPoolPercForMC = 10; + plotStakeForRewardPoolShare = 50000; } /** @@ -98,14 +101,21 @@ contract MarketRegistryNew is MarketRegistry { } function _checkIfCreatorStaked(address _market) internal { + uint256 tokensLocked = ITokenController(tokenController).tokensLockedAtTime(msg.sender, "SM", now); if( - ITokenController(tokenController).tokensLockedAtTime(msg.sender, "SM", now) - >= plotStakeForRewardPoolShare) + tokensLocked >= plotStakeForRewardPoolShare) { marketCreationRewardData[_market].rewardPoolShareApplicable = true; + marketCreationRewardData[_market].rewardPoolSharePerc + = uint8(Math.min(rewardPoolPercForMC, tokensLocked.div(plotStakeForRewardPoolShare))); + } } + function getMarketCreatorRPoolSharePerc(address _market) external view returns(uint256) { + return marketCreationRewardData[_market].rewardPoolSharePerc; + } + /** * @dev internal function to calculate gas price for market creation incentives */ diff --git a/contracts/interfaces/IMarketRegistry.sol b/contracts/interfaces/IMarketRegistry.sol index e31c4d2b..4afcee50 100644 --- a/contracts/interfaces/IMarketRegistry.sol +++ b/contracts/interfaces/IMarketRegistry.sol @@ -27,6 +27,8 @@ contract IMarketRegistry { function getUintParameters(bytes8 code) external view returns(bytes8 codeVal, uint256 value); + function getMarketCreatorRPoolSharePerc(address _market) external view returns(uint256); + /** * @dev Initialize the PlotX. * @param _marketConfig The address of market config. From 1f4810bde58096b794b3de648457a4afeb8e7cfb Mon Sep 17 00:00:00 2001 From: udkreddySomish Date: Sat, 31 Oct 2020 10:36:25 +0530 Subject: [PATCH 28/58] Updated plot stake required for reward pool share percent --- contracts/MarketRegistryNew.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/MarketRegistryNew.sol b/contracts/MarketRegistryNew.sol index 8df3d38d..06e2666e 100644 --- a/contracts/MarketRegistryNew.sol +++ b/contracts/MarketRegistryNew.sol @@ -53,7 +53,7 @@ contract MarketRegistryNew is MarketRegistry { clGasPriceAggregator = IChainLinkOracle(_clGasPriceAggregator); maxGasPrice = 100 * 10**9; rewardPoolPercForMC = 10; - plotStakeForRewardPoolShare = 50000; + plotStakeForRewardPoolShare = 500000; } /** From cb76e1523763753a76b0bbb8ad3119164e50f0b1 Mon Sep 17 00:00:00 2001 From: udkreddySomish Date: Sat, 31 Oct 2020 10:40:59 +0530 Subject: [PATCH 29/58] Updated plot stake required for reward pool share percent --- contracts/MarketRegistryNew.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/MarketRegistryNew.sol b/contracts/MarketRegistryNew.sol index 06e2666e..8df3d38d 100644 --- a/contracts/MarketRegistryNew.sol +++ b/contracts/MarketRegistryNew.sol @@ -53,7 +53,7 @@ contract MarketRegistryNew is MarketRegistry { clGasPriceAggregator = IChainLinkOracle(_clGasPriceAggregator); maxGasPrice = 100 * 10**9; rewardPoolPercForMC = 10; - plotStakeForRewardPoolShare = 500000; + plotStakeForRewardPoolShare = 50000; } /** From d8849e89d47bc0d63cfeb3406be9c029849759ab Mon Sep 17 00:00:00 2001 From: udkreddySomish Date: Sat, 31 Oct 2020 11:54:15 +0530 Subject: [PATCH 30/58] Corrected formulae for reward pool share percent --- contracts/MarketRegistryNew.sol | 29 ++++++++++------------------- 1 file changed, 10 insertions(+), 19 deletions(-) diff --git a/contracts/MarketRegistryNew.sol b/contracts/MarketRegistryNew.sol index 8df3d38d..c9f0ca84 100644 --- a/contracts/MarketRegistryNew.sol +++ b/contracts/MarketRegistryNew.sol @@ -102,14 +102,8 @@ contract MarketRegistryNew is MarketRegistry { function _checkIfCreatorStaked(address _market) internal { uint256 tokensLocked = ITokenController(tokenController).tokensLockedAtTime(msg.sender, "SM", now); - if( - tokensLocked >= plotStakeForRewardPoolShare) - { - marketCreationRewardData[_market].rewardPoolShareApplicable = true; - marketCreationRewardData[_market].rewardPoolSharePerc - = uint8(Math.min(rewardPoolPercForMC, tokensLocked.div(plotStakeForRewardPoolShare))); - - } + marketCreationRewardData[_market].rewardPoolSharePerc + = uint8(Math.min(rewardPoolPercForMC, 1 + tokensLocked.div(plotStakeForRewardPoolShare))); } function getMarketCreatorRPoolSharePerc(address _market) external view returns(uint256) { @@ -168,17 +162,14 @@ contract MarketRegistryNew is MarketRegistry { uint256 i; for(i = rewardData.lastClaimedIndex;i < len && count < _maxRecords; i++) { MarketCreationRewardData memory marketData = marketCreationRewardData[rewardData.marketsCreated[i]]; - if(marketData.rewardPoolShareApplicable) - { - ( , , , , , , , , uint _predictionStatus) = IMarket(rewardData.marketsCreated[i]).getData(); - if(_predictionStatus == uint(IMarket.PredictionStatus.Settled)) { - ethIncentive = ethIncentive.add(marketData.ethIncentive); - plotIncentive = plotIncentive.add(marketData.plotIncentive); - count++; - } else { - if(lastClaimed == len && (marketData.plotIncentive > 0 || marketData.ethIncentive > 0)) { - lastClaimed = i; - } + ( , , , , , , , , uint _predictionStatus) = IMarket(rewardData.marketsCreated[i]).getData(); + if(_predictionStatus == uint(IMarket.PredictionStatus.Settled)) { + ethIncentive = ethIncentive.add(marketData.ethIncentive); + plotIncentive = plotIncentive.add(marketData.plotIncentive); + count++; + } else { + if(lastClaimed == len && (marketData.plotIncentive > 0 || marketData.ethIncentive > 0)) { + lastClaimed = i; } } } From 37ce6f59943b03866e0d157dabf283ec5d7409b5 Mon Sep 17 00:00:00 2001 From: udkreddySomish Date: Sun, 1 Nov 2020 12:25:27 +0530 Subject: [PATCH 31/58] Corrected formulae --- contracts/MarketNew.sol | 4 ++-- contracts/MarketRegistryNew.sol | 21 +++++++++++------ test/24_UpgradedCreationIncentive.test.js | 28 +++++++++++++++++++++-- 3 files changed, 42 insertions(+), 11 deletions(-) diff --git a/contracts/MarketNew.sol b/contracts/MarketNew.sol index 60e59993..db98362c 100644 --- a/contracts/MarketNew.sol +++ b/contracts/MarketNew.sol @@ -253,8 +253,8 @@ contract MarketNew { totalReward[1] = totalReward[1].add(leveragedAsset); } } - marketCreatorIncentive[0] = _calculatePercentage(rewardPoolSharePerc, totalReward[0], 100); - marketCreatorIncentive[1] = _calculatePercentage(rewardPoolSharePerc, totalReward[1], 100); + marketCreatorIncentive[0] = _calculatePercentage(rewardPoolSharePerc, totalReward[0], 10000); + marketCreatorIncentive[1] = _calculatePercentage(rewardPoolSharePerc, totalReward[1], 10000); rewardToDistribute[0] = totalReward[0].sub(marketCreatorIncentive[0]); rewardToDistribute[1] = totalReward[1].sub(marketCreatorIncentive[1]); // rewardToDistribute = totalReward; diff --git a/contracts/MarketRegistryNew.sol b/contracts/MarketRegistryNew.sol index c9f0ca84..2b767e28 100644 --- a/contracts/MarketRegistryNew.sol +++ b/contracts/MarketRegistryNew.sol @@ -36,7 +36,8 @@ contract MarketRegistryNew is MarketRegistry { bool rewardPoolShareApplicable; } - uint256 rewardPoolPercForMC; + uint256 maxRewardPoolPercForMC; + uint256 minRewardPoolPercForMC; uint256 plotStakeForRewardPoolShare; mapping(address => MarketCreationRewardUserData) private marketCreationRewardUserData; //Of user @@ -52,7 +53,8 @@ contract MarketRegistryNew is MarketRegistry { require(msg.sender == marketInitiater); clGasPriceAggregator = IChainLinkOracle(_clGasPriceAggregator); maxGasPrice = 100 * 10**9; - rewardPoolPercForMC = 10; + maxRewardPoolPercForMC = 1000; // Raised by 2 decimals + minRewardPoolPercForMC = 100; // Raised by 2 decimals plotStakeForRewardPoolShare = 50000; } @@ -102,8 +104,9 @@ contract MarketRegistryNew is MarketRegistry { function _checkIfCreatorStaked(address _market) internal { uint256 tokensLocked = ITokenController(tokenController).tokensLockedAtTime(msg.sender, "SM", now); + //Intentionally performed mul operation after div, to get absolute value instead of decimals marketCreationRewardData[_market].rewardPoolSharePerc - = uint8(Math.min(rewardPoolPercForMC, 1 + tokensLocked.div(plotStakeForRewardPoolShare))); + = uint8(Math.min(maxRewardPoolPercForMC, minRewardPoolPercForMC + tokensLocked.div(plotStakeForRewardPoolShare).mul(100))); } function getMarketCreatorRPoolSharePerc(address _market) external view returns(uint256) { @@ -212,8 +215,10 @@ contract MarketRegistryNew is MarketRegistry { marketCreationIncentive = value; } else if(code == "MAXGAS") { // Maximum gas upto which is considered while calculating market creation incentives maxGasPrice = value; - } else if(code == "RPPERCMC") { // Reward Pool percent for market creator - rewardPoolPercForMC = value; + } else if(code == "MAXRPSP") { // Max Reward Pool percent for market creator + maxRewardPoolPercForMC = value; + } else if(code == "MINRPSP") { // Min Reward Pool percent for market creator + minRewardPoolPercForMC = value; } else if(code == "PSFRPS") { // Reward Pool percent for market creator plotStakeForRewardPoolShare = value; } else { @@ -230,8 +235,10 @@ contract MarketRegistryNew is MarketRegistry { value = marketCreationIncentive; } else if(code == "MAXGAS") { value = maxGasPrice; - } else if(code == "RPPERCMC") { - value = rewardPoolPercForMC; + } else if(code == "MAXRPSP") { + value = maxRewardPoolPercForMC; + } else if(code == "MINRPSP") { + value = minRewardPoolPercForMC; } else if(code == "PSFRPS") { value = plotStakeForRewardPoolShare; } diff --git a/test/24_UpgradedCreationIncentive.test.js b/test/24_UpgradedCreationIncentive.test.js index a40cf898..da659cb7 100644 --- a/test/24_UpgradedCreationIncentive.test.js +++ b/test/24_UpgradedCreationIncentive.test.js @@ -1,6 +1,7 @@ const { assert } = require("chai"); const OwnedUpgradeabilityProxy = artifacts.require("OwnedUpgradeabilityProxy"); const Market = artifacts.require("MockMarket"); +const MarketNew = artifacts.require("MarketNew"); const Plotus = artifacts.require("MarketRegistry"); const MarketRegistryNew = artifacts.require("MarketRegistryNew"); const MockChainLinkGasPriceAgg = artifacts.require("MockChainLinkGasPriceAgg"); @@ -170,6 +171,29 @@ contract("MarketUtility", async function([user1, user2, user3, user4, user5, use await assertRevert(plotusNewInstance.setGasPriceAggAndMaxGas(chainlinkGasAgg.address, {from:user2})); }); + it('Should Update Market Implementations', async function() { + let market1 = await MarketNew.new(); + let market2 = await MarketNew.new(); + let actionHash = encode1( + ['uint256[]', 'address[]'], + [ + [0,1], + [market1.address, market2.address] + ] + ); + let proposalLength =(await governance.getProposalLength())/1; + await gvProposal( + 5, + actionHash, + await MemberRoles.at(await masterInstance.getLatestAddress(toHex('MR'))), + governance, + 2, + 0 + ); + assert.equal((await governance.proposalActionStatus(proposalLength))/1, 3) + await increaseTime(604800); + }); + it("Should be able to claim market creation rewards of pre upgrade", async function() { let oldBalance = parseFloat(await plotusToken.balanceOf(user1)); await plotusNewInstance.claimCreationReward(); @@ -178,7 +202,7 @@ contract("MarketUtility", async function([user1, user2, user3, user4, user5, use }); it("Should not be able to claim the market creation rewards if not created any market", async function() { - let tx = await assertRevert(plotusNewInstance.claimCreationRewardV2()); + let tx = await assertRevert(plotusNewInstance.claimCreationRewardV2(100)); }); it("Should create Markets", async function() { @@ -251,7 +275,7 @@ contract("MarketUtility", async function([user1, user2, user3, user4, user5, use it("Should be able to claim the market creation rewards", async function() { let oldBalance = parseFloat(await plotusToken.balanceOf(user1)); - let tx = await plotusNewInstance.claimCreationRewardV2(); + let tx = await plotusNewInstance.claimCreationRewardV2(100); let newBalance = parseFloat(await plotusToken.balanceOf(user1)); assert.equal((newBalance/1e18).toFixed(2), (oldBalance/1e18 + incentivesGained/1e18).toFixed(2)); }); From ab5dbd023d2b160205836b49f6ea13c08db164f6 Mon Sep 17 00:00:00 2001 From: udkreddySomish Date: Sun, 1 Nov 2020 15:21:25 +0530 Subject: [PATCH 32/58] Removed unused variables --- contracts/MarketRegistryNew.sol | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/contracts/MarketRegistryNew.sol b/contracts/MarketRegistryNew.sol index 2b767e28..9a7ebb45 100644 --- a/contracts/MarketRegistryNew.sol +++ b/contracts/MarketRegistryNew.sol @@ -32,8 +32,7 @@ contract MarketRegistryNew is MarketRegistry { struct MarketCreationRewardData { uint ethIncentive; uint plotIncentive; - uint8 rewardPoolSharePerc; - bool rewardPoolShareApplicable; + uint rewardPoolSharePerc; } uint256 maxRewardPoolPercForMC; @@ -106,7 +105,7 @@ contract MarketRegistryNew is MarketRegistry { uint256 tokensLocked = ITokenController(tokenController).tokensLockedAtTime(msg.sender, "SM", now); //Intentionally performed mul operation after div, to get absolute value instead of decimals marketCreationRewardData[_market].rewardPoolSharePerc - = uint8(Math.min(maxRewardPoolPercForMC, minRewardPoolPercForMC + tokensLocked.div(plotStakeForRewardPoolShare).mul(100))); + = Math.min(maxRewardPoolPercForMC, minRewardPoolPercForMC + tokensLocked.div(plotStakeForRewardPoolShare).mul(100)); } function getMarketCreatorRPoolSharePerc(address _market) external view returns(uint256) { From 390af34f6495096b45fed39ae9be925c40d7205d Mon Sep 17 00:00:00 2001 From: udkreddySomish Date: Sun, 1 Nov 2020 15:24:58 +0530 Subject: [PATCH 33/58] Added code comments --- contracts/MarketRegistryNew.sol | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/contracts/MarketRegistryNew.sol b/contracts/MarketRegistryNew.sol index 9a7ebb45..63886bc3 100644 --- a/contracts/MarketRegistryNew.sol +++ b/contracts/MarketRegistryNew.sol @@ -101,6 +101,9 @@ contract MarketRegistryNew is MarketRegistry { emit MarketCreationReward(msg.sender, incentive, gasUsed, gasCost, gasPrice, tx.gasprice, maxGasPrice); } + /** + * @dev internal function to calculate market reward pool share percent to be rewarded to market creator + */ function _checkIfCreatorStaked(address _market) internal { uint256 tokensLocked = ITokenController(tokenController).tokensLockedAtTime(msg.sender, "SM", now); //Intentionally performed mul operation after div, to get absolute value instead of decimals @@ -108,6 +111,9 @@ contract MarketRegistryNew is MarketRegistry { = Math.min(maxRewardPoolPercForMC, minRewardPoolPercForMC + tokensLocked.div(plotStakeForRewardPoolShare).mul(100)); } + /** + * @dev Get market reward pool share percent to be rewarded to market creator + */ function getMarketCreatorRPoolSharePerc(address _market) external view returns(uint256) { return marketCreationRewardData[_market].rewardPoolSharePerc; } @@ -156,6 +162,9 @@ contract MarketRegistryNew is MarketRegistry { emit ClaimedMarketCreationReward(msg.sender, ethIncentive, pendingPLOTReward); } + /** + * @dev internal function to calculate market reward pool share incentives for market creator + */ function _getRewardPoolIncentives(uint256 _maxRecords) internal returns(uint256 ethIncentive, uint256 plotIncentive) { MarketCreationRewardUserData storage rewardData = marketCreationRewardUserData[msg.sender]; uint256 len = rewardData.marketsCreated.length; From 9ddc41ecec91beede8198cd4482ca4d5f025c4a8 Mon Sep 17 00:00:00 2001 From: udkreddySomish Date: Mon, 2 Nov 2020 07:44:09 +0530 Subject: [PATCH 34/58] Updated MarketCreationReward eventdata --- contracts/MarketRegistryNew.sol | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/contracts/MarketRegistryNew.sol b/contracts/MarketRegistryNew.sol index 63886bc3..aefa34bb 100644 --- a/contracts/MarketRegistryNew.sol +++ b/contracts/MarketRegistryNew.sol @@ -41,7 +41,7 @@ contract MarketRegistryNew is MarketRegistry { mapping(address => MarketCreationRewardUserData) private marketCreationRewardUserData; //Of user mapping(address => MarketCreationRewardData) private marketCreationRewardData; //Of user - event MarketCreationReward(address indexed createdBy, uint256 plotIncentive, uint256 gasUsed, uint256 gasCost, uint256 gasPriceConsidered, uint256 gasPriceGiven, uint256 maxGasCap); + event MarketCreationReward(address indexed createdBy, address marketAddress, uint256 plotIncentive, uint256 gasUsed, uint256 gasCost, uint256 gasPriceConsidered, uint256 gasPriceGiven, uint256 maxGasCap, uint256 rewardPoolSharePerc); event ClaimedMarketCreationReward(address indexed user, uint256 ethIncentive, uint256 plotIncentive); /** @@ -85,20 +85,21 @@ contract MarketRegistryNew is MarketRegistry { _checkIfCreatorStaked(marketCreationData[_marketType][_marketCurrencyIndex].marketAddress); marketCreationRewardUserData[msg.sender].marketsCreated.push(marketCreationData[_marketType][_marketCurrencyIndex].marketAddress); uint256 gasUsed = gasProvided - gasleft(); - _calculateIncentive(gasUsed); + _calculateIncentive(gasUsed, _marketType, _marketCurrencyIndex); } /** * @dev internal function to calculate user incentive for market creation */ - function _calculateIncentive(uint256 gasUsed) internal{ + function _calculateIncentive(uint256 gasUsed, uint256 _marketType, uint256 _marketCurrencyIndex) internal{ + address _marketAddress = marketCreationData[_marketType][_marketCurrencyIndex].marketAddress; //Adding buffer gas for below calculations gasUsed = gasUsed + 38500; uint256 gasPrice = _checkGasPrice(); uint256 gasCost = gasUsed.mul(gasPrice); (, uint256 incentive) = marketUtility.getValueAndMultiplierParameters(ETH_ADDRESS, gasCost); marketCreationRewardUserData[msg.sender].incentives = marketCreationRewardUserData[msg.sender].incentives.add(incentive); - emit MarketCreationReward(msg.sender, incentive, gasUsed, gasCost, gasPrice, tx.gasprice, maxGasPrice); + emit MarketCreationReward(msg.sender, _marketAddress, incentive, gasUsed, gasCost, gasPrice, tx.gasprice, maxGasPrice, marketCreationRewardData[_marketAddress].rewardPoolSharePerc); } /** @@ -108,7 +109,10 @@ contract MarketRegistryNew is MarketRegistry { uint256 tokensLocked = ITokenController(tokenController).tokensLockedAtTime(msg.sender, "SM", now); //Intentionally performed mul operation after div, to get absolute value instead of decimals marketCreationRewardData[_market].rewardPoolSharePerc - = Math.min(maxRewardPoolPercForMC, minRewardPoolPercForMC + tokensLocked.div(plotStakeForRewardPoolShare).mul(100)); + = Math.min( + maxRewardPoolPercForMC, + minRewardPoolPercForMC + tokensLocked.div(plotStakeForRewardPoolShare).mul(100) + ); } /** From bcf1c3088ac77241416667df2b5ac6ac2f811879 Mon Sep 17 00:00:00 2001 From: udkreddySomish Date: Mon, 2 Nov 2020 09:51:45 +0530 Subject: [PATCH 35/58] Fixed minor issues --- contracts/MarketNew.sol | 8 ++++++-- contracts/MarketRegistryNew.sol | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/contracts/MarketNew.sol b/contracts/MarketNew.sol index db98362c..25f90927 100644 --- a/contracts/MarketNew.sol +++ b/contracts/MarketNew.sol @@ -265,9 +265,13 @@ contract MarketNew { leveragedAsset = _calculatePercentage(riskPercentage, optionsAvailable[i].assetLeveraged[ETH_ADDRESS], 100); ethAmountToPool = ethAmountToPool.add(leveragedAsset); } + marketCreatorIncentive[0] = _calculatePercentage(rewardPoolSharePerc, tokenAmountToPool, 10000); + marketCreatorIncentive[1] = _calculatePercentage(rewardPoolSharePerc, ethAmountToPool, 10000); + tokenAmountToPool = tokenAmountToPool.sub(marketCreatorIncentive[0]); + ethAmountToPool = ethAmountToPool.sub(marketCreatorIncentive[1]); } - _transferAsset(ETH_ADDRESS, address(marketRegistry), ethAmountToPool.add(ethCommissionAmount)); - _transferAsset(plotToken, address(marketRegistry), tokenAmountToPool.add(plotCommissionAmount)); + _transferAsset(ETH_ADDRESS, address(marketRegistry), ethAmountToPool.add(ethCommissionAmount).add(marketCreatorIncentive[1])); + _transferAsset(plotToken, address(marketRegistry), tokenAmountToPool.add(plotCommissionAmount).add(marketCreatorIncentive[0])); delete ethCommissionAmount; delete plotCommissionAmount; marketRegistry.callMarketResultEvent(rewardToDistribute, marketCreatorIncentive, marketSettleData.WinningOption, _value, _roundId); diff --git a/contracts/MarketRegistryNew.sol b/contracts/MarketRegistryNew.sol index aefa34bb..5da8f852 100644 --- a/contracts/MarketRegistryNew.sol +++ b/contracts/MarketRegistryNew.sol @@ -54,7 +54,7 @@ contract MarketRegistryNew is MarketRegistry { maxGasPrice = 100 * 10**9; maxRewardPoolPercForMC = 1000; // Raised by 2 decimals minRewardPoolPercForMC = 100; // Raised by 2 decimals - plotStakeForRewardPoolShare = 50000; + plotStakeForRewardPoolShare = 50000 ether; } /** From 060007003b7ea5b93d36becd2418b0e5bcd6c162 Mon Sep 17 00:00:00 2001 From: udkreddySomish Date: Mon, 2 Nov 2020 10:20:18 +0530 Subject: [PATCH 36/58] Updated testcases for Market creation incentives --- test/24_UpgradedCreationIncentive.test.js | 251 ++++++++++++++++++++++ 1 file changed, 251 insertions(+) diff --git a/test/24_UpgradedCreationIncentive.test.js b/test/24_UpgradedCreationIncentive.test.js index da659cb7..b127c6d9 100644 --- a/test/24_UpgradedCreationIncentive.test.js +++ b/test/24_UpgradedCreationIncentive.test.js @@ -280,6 +280,257 @@ contract("MarketUtility", async function([user1, user2, user3, user4, user5, use assert.equal((newBalance/1e18).toFixed(2), (oldBalance/1e18 + incentivesGained/1e18).toFixed(2)); }); + it("Scenario 1: Should be able to get reward pool share of market", async function() { + await chainlinkGasAgg.setLatestAnswer(450000); + await increaseTime(3610); + let tx = await plotusNewInstance.createMarket(0,1, {gasPrice:450000, from:user2}); + let openMarkets = await plotusNewInstance.getOpenMarkets(); + let marketInstance = await MarketNew.at(openMarkets[0][1]); + await increaseTime(100); + await marketInstance.placePrediction(ethAddress, "100000000000000000", 3, 5, { + value: "100000000000000000", + from: user7, + }); + await plotusToken.transfer(user7, toWei(10000)); + await plotusToken.approve(tokenController.address, toWei(1000000000000000000), {from: user7}); + await marketInstance.placePrediction(plotusToken.address, "100000000000000000000", 3, 5, { + from: user7, + }); + let rewardPoolEth = 0.1; + let rewardPoolPlot = 100; + eventData = tx.logs[2].args; + let gasUsed = eventData.gasUsed.toNumber(); + let maxGas = await plotusNewInstance.getUintParameters(toHex("MAXGAS")); + let gasPrice = Math.min(maxGas[1].toNumber(), 450000*1.25); + estimatedGasCost = gasPrice*gasUsed; + let costInETH = estimatedGasCost; + let worthInPLOT = await marketConfig.getValueAndMultiplierParameters(ethAddress, costInETH + ""); + incentivesGained = eventData.plotIncentive/1; + let rewardPoolSharePerc = eventData.rewardPoolSharePerc; + assert.equal(rewardPoolSharePerc/1, 100) + assert.equal(eventData.plotIncentive/1, worthInPLOT[1]/1); + await increaseTime(10000); + await marketInstance.settleMarket(); + await increaseTime(10000); + let oldBalance = parseFloat(await plotusToken.balanceOf(user2)); + let oldBalanceEth = parseFloat(await web3.eth.getBalance(user2)); + tx = await plotusNewInstance.claimCreationRewardV2(100, {from:user2}); + let newBalance = parseFloat(await plotusToken.balanceOf(user2)); + let newBalanceEth = parseFloat(await web3.eth.getBalance(user2)); + assert.equal((newBalance/1e18).toFixed(2), (oldBalance/1e18 + incentivesGained/1e18 + rewardPoolPlot/100).toFixed(2)); + assert.equal((newBalanceEth/1e18).toFixed(2), (oldBalanceEth/1e18 + rewardPoolEth/100).toFixed(2)); + }); + + it("Scenario 2: Should be able to get more reward pool share of market if market creator had staked tokens", async function() { + await plotusToken.transfer(user3, toWei(50000)); + await plotusToken.approve(tokenController.address, "1000000000000000000000000", { from: user3 }); + await tokenController.lock("0x534d", toWei(50000), 86400 * 30, { from: user3 }); + await chainlinkGasAgg.setLatestAnswer(450000); + await increaseTime(3610); + let tx = await plotusNewInstance.createMarket(0,1, {gasPrice:450000, from:user3}); + let openMarkets = await plotusNewInstance.getOpenMarkets(); + let marketInstance = await MarketNew.at(openMarkets[0][1]); + await increaseTime(100); + await marketInstance.placePrediction(ethAddress, "100000000000000000", 3, 5, { + value: "100000000000000000", + from: user7, + }); + await plotusToken.transfer(user7, toWei(10000)); + await plotusToken.approve(tokenController.address, toWei(1000000000000000000), {from: user7}); + await marketInstance.placePrediction(plotusToken.address, "100000000000000000000", 3, 5, { + from: user7, + }); + let rewardPoolEth = 0.2; + let rewardPoolPlot = 200; + eventData = tx.logs[2].args; + let gasUsed = eventData.gasUsed.toNumber(); + let maxGas = await plotusNewInstance.getUintParameters(toHex("MAXGAS")); + let gasPrice = Math.min(maxGas[1].toNumber(), 450000*1.25); + estimatedGasCost = gasPrice*gasUsed; + let costInETH = estimatedGasCost; + let worthInPLOT = await marketConfig.getValueAndMultiplierParameters(ethAddress, costInETH + ""); + incentivesGained = eventData.plotIncentive/1; + let rewardPoolSharePerc = eventData.rewardPoolSharePerc; + assert.equal(rewardPoolSharePerc/1, 200) + assert.equal(eventData.plotIncentive/1, worthInPLOT[1]/1); + await increaseTime(10000); + await marketInstance.settleMarket(); + await increaseTime(10000); + let oldBalance = parseFloat(await plotusToken.balanceOf(user3)); + let oldBalanceEth = parseFloat(await web3.eth.getBalance(user3)); + tx = await plotusNewInstance.claimCreationRewardV2(100, {from:user3}); + let newBalance = parseFloat(await plotusToken.balanceOf(user3)); + let newBalanceEth = parseFloat(await web3.eth.getBalance(user3)); + assert.equal((newBalance/1e18).toFixed(2), (oldBalance/1e18 + incentivesGained/1e18 + rewardPoolPlot/100).toFixed(2)); + assert.equal((newBalanceEth/1e18).toFixed(2), (oldBalanceEth/1e18 + rewardPoolEth/100).toFixed(2)); + }); + + it("Scenario 3: Should be able to get more reward pool share of market if market creator had staked tokens", async function() { + await plotusToken.transfer(user4, toWei(90000)); + await plotusToken.approve(tokenController.address, "1000000000000000000000000", { from: user4 }); + await tokenController.lock("0x534d", toWei(50000), 86400 * 30, { from: user4 }); + await chainlinkGasAgg.setLatestAnswer(450000); + await increaseTime(3610); + let tx = await plotusNewInstance.createMarket(0,1, {gasPrice:450000, from:user4}); + eventData = tx.logs[1].args; + let openMarkets = await plotusNewInstance.getOpenMarkets(); + let marketInstance = await MarketNew.at(openMarkets[0][1]); + await increaseTime(100); + await marketInstance.placePrediction(ethAddress, "100000000000000000", 3, 5, { + value: "100000000000000000", + from: user7, + }); + await plotusToken.transfer(user7, toWei(10000)); + await plotusToken.approve(tokenController.address, toWei(1000000000000000000), {from: user7}); + await marketInstance.placePrediction(plotusToken.address, "100000000000000000000", 3, 5, { + from: user7, + }); + let rewardPoolEth = 0.2; + let rewardPoolPlot = 200; + let gasUsed = eventData.gasUsed.toNumber(); + let maxGas = await plotusNewInstance.getUintParameters(toHex("MAXGAS")); + let gasPrice = Math.min(maxGas[1].toNumber(), 450000*1.25); + estimatedGasCost = gasPrice*gasUsed; + let costInETH = estimatedGasCost; + let worthInPLOT = await marketConfig.getValueAndMultiplierParameters(ethAddress, costInETH + ""); + incentivesGained = eventData.plotIncentive/1; + let rewardPoolSharePerc = eventData.rewardPoolSharePerc; + assert.equal(rewardPoolSharePerc/1, 200) + assert.equal(eventData.plotIncentive/1, worthInPLOT[1]/1); + await increaseTime(10000); + await marketInstance.settleMarket(); + await increaseTime(10000); + let oldBalance = parseFloat(await plotusToken.balanceOf(user4)); + let oldBalanceEth = parseFloat(await web3.eth.getBalance(user4)); + tx = await plotusNewInstance.claimCreationRewardV2(100, {from:user4}); + let newBalance = parseFloat(await plotusToken.balanceOf(user4)); + let newBalanceEth = parseFloat(await web3.eth.getBalance(user4)); + assert.equal((newBalance/1e18).toFixed(2), (oldBalance/1e18 + incentivesGained/1e18 + rewardPoolPlot/100).toFixed(2)); + assert.equal((newBalanceEth/1e18).toFixed(2), (oldBalanceEth/1e18 + rewardPoolEth/100).toFixed(2)); + }); + + it("Scenario 4: Should be able to get more reward pool share of market if market creator had staked tokens", async function() { + await plotusToken.transfer(user5, toWei(100000)); + await plotusToken.approve(tokenController.address, "1000000000000000000000000", { from: user5 }); + await tokenController.lock("0x534d", toWei(100000), 86400 * 30, { from: user5 }); + await chainlinkGasAgg.setLatestAnswer(450000); + await increaseTime(3610); + let tx = await plotusNewInstance.createMarket(0,1, {gasPrice:450000, from:user5}); + let openMarkets = await plotusNewInstance.getOpenMarkets(); + let marketInstance = await MarketNew.at(openMarkets[0][1]); + await increaseTime(100); + await marketInstance.placePrediction(ethAddress, "100000000000000000", 3, 5, { + value: "100000000000000000", + from: user7, + }); + await plotusToken.transfer(user7, toWei(10000)); + await plotusToken.approve(tokenController.address, toWei(1000000000000000000), {from: user7}); + await marketInstance.placePrediction(plotusToken.address, "100000000000000000000", 3, 5, { + from: user7, + }); + let rewardPoolEth = 0.3; + let rewardPoolPlot = 300; + eventData = tx.logs[1].args; + let gasUsed = eventData.gasUsed.toNumber(); + let maxGas = await plotusNewInstance.getUintParameters(toHex("MAXGAS")); + let gasPrice = Math.min(maxGas[1].toNumber(), 450000*1.25); + estimatedGasCost = gasPrice*gasUsed; + let costInETH = estimatedGasCost; + let worthInPLOT = await marketConfig.getValueAndMultiplierParameters(ethAddress, costInETH + ""); + incentivesGained = eventData.plotIncentive/1; + let rewardPoolSharePerc = eventData.rewardPoolSharePerc; + assert.equal(rewardPoolSharePerc/1, 300) + assert.equal(eventData.plotIncentive/1, worthInPLOT[1]/1); + await increaseTime(10000); + await marketInstance.settleMarket(); + await increaseTime(10000); + let oldBalance = parseFloat(await plotusToken.balanceOf(user5)); + let oldBalanceEth = parseFloat(await web3.eth.getBalance(user5)); + tx = await plotusNewInstance.claimCreationRewardV2(100, {from:user5}); + let newBalance = parseFloat(await plotusToken.balanceOf(user5)); + let newBalanceEth = parseFloat(await web3.eth.getBalance(user5)); + assert.equal((newBalance/1e18).toFixed(2), (oldBalance/1e18 + incentivesGained/1e18 + rewardPoolPlot/100).toFixed(2)); + assert.equal((newBalanceEth/1e18).toFixed(2), (oldBalanceEth/1e18 + rewardPoolEth/100).toFixed(2)); + }); + + it("Scenario 5: Should be able to get more reward pool share of market if market creator had staked tokens", async function() { + await plotusToken.transfer(user6, toWei(150000)); + await plotusToken.approve(tokenController.address, "1000000000000000000000000", { from: user6 }); + await tokenController.lock("0x534d", toWei(150000), 86400 * 30, { from: user6 }); + await chainlinkGasAgg.setLatestAnswer(450000); + await increaseTime(3610); + let tx = await plotusNewInstance.createMarket(0,1, {gasPrice:450000, from:user6}); + let openMarkets = await plotusNewInstance.getOpenMarkets(); + let marketInstance = await MarketNew.at(openMarkets[0][1]); + await increaseTime(100); + await marketInstance.placePrediction(ethAddress, "100000000000000000", 3, 5, { + value: "100000000000000000", + from: user7, + }); + await plotusToken.transfer(user7, toWei(10000)); + await plotusToken.approve(tokenController.address, toWei(1000000000000000000), {from: user7}); + await marketInstance.placePrediction(plotusToken.address, "100000000000000000000", 3, 5, { + from: user7, + }); + let rewardPoolEth = 0.4; + let rewardPoolPlot = 400; + eventData = tx.logs[1].args; + let gasUsed = eventData.gasUsed.toNumber(); + let maxGas = await plotusNewInstance.getUintParameters(toHex("MAXGAS")); + let gasPrice = Math.min(maxGas[1].toNumber(), 450000*1.25); + estimatedGasCost = gasPrice*gasUsed; + let costInETH = estimatedGasCost; + let worthInPLOT = await marketConfig.getValueAndMultiplierParameters(ethAddress, costInETH + ""); + incentivesGained = eventData.plotIncentive/1; + let rewardPoolSharePerc = eventData.rewardPoolSharePerc; + assert.equal(rewardPoolSharePerc/1, 400) + assert.equal(eventData.plotIncentive/1, worthInPLOT[1]/1); + await increaseTime(10000); + await marketInstance.settleMarket(); + await increaseTime(10000); + let oldBalance = parseFloat(await plotusToken.balanceOf(user6)); + let oldBalanceEth = parseFloat(await web3.eth.getBalance(user6)); + tx = await plotusNewInstance.claimCreationRewardV2(100, {from:user6}); + let newBalance = parseFloat(await plotusToken.balanceOf(user6)); + let newBalanceEth = parseFloat(await web3.eth.getBalance(user6)); + assert.equal((newBalance/1e18).toFixed(2), (oldBalance/1e18 + incentivesGained/1e18 + rewardPoolPlot/100).toFixed(2)); + assert.equal((newBalanceEth/1e18).toFixed(2), (oldBalanceEth/1e18 + rewardPoolEth/100).toFixed(2)); + }); + + it("Scenario 6: Should be able to get more reward pool share of market if market creator had staked tokens", async function() { + await plotusToken.transfer(user8, toWei(150000)); + await plotusToken.approve(tokenController.address, "1000000000000000000000000", { from: user8 }); + await tokenController.lock("0x534d", toWei(150000), 86400 * 30, { from: user8 }); + await chainlinkGasAgg.setLatestAnswer(450000); + await increaseTime(3610); + let tx = await plotusNewInstance.createMarket(0,1, {gasPrice:450000, from:user8}); + let openMarkets = await plotusNewInstance.getOpenMarkets(); + let marketInstance = await MarketNew.at(openMarkets[0][1]); + let rewardPoolEth = 0; + let rewardPoolPlot = 0; + eventData = tx.logs[1].args; + let gasUsed = eventData.gasUsed.toNumber(); + let maxGas = await plotusNewInstance.getUintParameters(toHex("MAXGAS")); + let gasPrice = Math.min(maxGas[1].toNumber(), 450000*1.25); + estimatedGasCost = gasPrice*gasUsed; + let costInETH = estimatedGasCost; + let worthInPLOT = await marketConfig.getValueAndMultiplierParameters(ethAddress, costInETH + ""); + incentivesGained = eventData.plotIncentive/1; + let rewardPoolSharePerc = eventData.rewardPoolSharePerc; + assert.equal(rewardPoolSharePerc/1, 400) + assert.equal(eventData.plotIncentive/1, worthInPLOT[1]/1); + await increaseTime(10000); + await marketInstance.settleMarket(); + await increaseTime(10000); + let oldBalance = parseFloat(await plotusToken.balanceOf(user8)); + let oldBalanceEth = parseFloat(await web3.eth.getBalance(user8)); + tx = await plotusNewInstance.claimCreationRewardV2(100, {from:user8}); + let newBalance = parseFloat(await plotusToken.balanceOf(user8)); + let newBalanceEth = parseFloat(await web3.eth.getBalance(user8)); + assert.equal((newBalance/1e18).toFixed(2), (oldBalance/1e18 + incentivesGained/1e18 + rewardPoolPlot/100).toFixed(2)); + assert.equal((newBalanceEth/1e18).toFixed(2), (oldBalanceEth/1e18 + rewardPoolEth/100).toFixed(2)); + }); + it('Should update Chainlink gas aggrefgartor address', async function() { let clAgg = await MockChainLinkGasPriceAgg.new(); await updateParameter(21, 2, 'GASAGG', plotusNewInstance, 'configAddress', clAgg.address); From c56df090cc94abd8d17afbbfea1570568a3c46d2 Mon Sep 17 00:00:00 2001 From: udkreddySomish Date: Mon, 2 Nov 2020 10:51:14 +0530 Subject: [PATCH 37/58] Fix broken test cases --- test/01_hourlyMarketOptionPrice.js | 4 ++-- test/24_UpgradedCreationIncentive.test.js | 24 +++++++++++++++++------ 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/test/01_hourlyMarketOptionPrice.js b/test/01_hourlyMarketOptionPrice.js index 92ad1b5f..38b6c28f 100644 --- a/test/01_hourlyMarketOptionPrice.js +++ b/test/01_hourlyMarketOptionPrice.js @@ -434,8 +434,8 @@ contract("Market", async function([user1, user2, user3, user4, user5, user6, use assert.equal(parseFloat(Math.floor((optionPriceETH2 / 1000) * 100) / 100), 0.15); assert.equal(parseFloat(Math.floor((optionPriceETH3 / 1000) * 100) / 100), 0.08); assert.equal(parseInt(optionPriceLOT1 / 1000) , parseInt(11.33)); - assert.equal(parseInt(optionPriceLOT2 / 1000) , parseInt(12.5)); - assert.equal(parseInt(optionPriceLOT3 / 1000) , parseInt(6.66)); + assert.equal(parseInt((parseFloat(Math.floor((optionPriceETH2 / 1000) * 100) / 100))/tokenPrice) , parseInt(12.5)); + assert.equal(parseInt((parseFloat(Math.floor((optionPriceETH3 / 1000) * 100) / 100))/tokenPrice) , parseInt(6.66)); }); }); diff --git a/test/24_UpgradedCreationIncentive.test.js b/test/24_UpgradedCreationIncentive.test.js index b127c6d9..de6cae17 100644 --- a/test/24_UpgradedCreationIncentive.test.js +++ b/test/24_UpgradedCreationIncentive.test.js @@ -333,7 +333,7 @@ contract("MarketUtility", async function([user1, user2, user3, user4, user5, use await increaseTime(100); await marketInstance.placePrediction(ethAddress, "100000000000000000", 3, 5, { value: "100000000000000000", - from: user7, + from: user12, }); await plotusToken.transfer(user7, toWei(10000)); await plotusToken.approve(tokenController.address, toWei(1000000000000000000), {from: user7}); @@ -378,7 +378,7 @@ contract("MarketUtility", async function([user1, user2, user3, user4, user5, use await increaseTime(100); await marketInstance.placePrediction(ethAddress, "100000000000000000", 3, 5, { value: "100000000000000000", - from: user7, + from: user12, }); await plotusToken.transfer(user7, toWei(10000)); await plotusToken.approve(tokenController.address, toWei(1000000000000000000), {from: user7}); @@ -421,7 +421,7 @@ contract("MarketUtility", async function([user1, user2, user3, user4, user5, use await increaseTime(100); await marketInstance.placePrediction(ethAddress, "100000000000000000", 3, 5, { value: "100000000000000000", - from: user7, + from: user12, }); await plotusToken.transfer(user7, toWei(10000)); await plotusToken.approve(tokenController.address, toWei(1000000000000000000), {from: user7}); @@ -430,7 +430,11 @@ contract("MarketUtility", async function([user1, user2, user3, user4, user5, use }); let rewardPoolEth = 0.3; let rewardPoolPlot = 300; - eventData = tx.logs[1].args; + try { + eventData = tx.logs[2].args; + } catch(e) { + eventData = tx.logs[1].args; + } let gasUsed = eventData.gasUsed.toNumber(); let maxGas = await plotusNewInstance.getUintParameters(toHex("MAXGAS")); let gasPrice = Math.min(maxGas[1].toNumber(), 450000*1.25); @@ -474,7 +478,11 @@ contract("MarketUtility", async function([user1, user2, user3, user4, user5, use }); let rewardPoolEth = 0.4; let rewardPoolPlot = 400; - eventData = tx.logs[1].args; + try { + eventData = tx.logs[2].args; + } catch(e) { + eventData = tx.logs[1].args; + } let gasUsed = eventData.gasUsed.toNumber(); let maxGas = await plotusNewInstance.getUintParameters(toHex("MAXGAS")); let gasPrice = Math.min(maxGas[1].toNumber(), 450000*1.25); @@ -508,7 +516,11 @@ contract("MarketUtility", async function([user1, user2, user3, user4, user5, use let marketInstance = await MarketNew.at(openMarkets[0][1]); let rewardPoolEth = 0; let rewardPoolPlot = 0; - eventData = tx.logs[1].args; + try { + eventData = tx.logs[2].args; + } catch(e) { + eventData = tx.logs[1].args; + } let gasUsed = eventData.gasUsed.toNumber(); let maxGas = await plotusNewInstance.getUintParameters(toHex("MAXGAS")); let gasPrice = Math.min(maxGas[1].toNumber(), 450000*1.25); From 6020c5af567c6948d27a499625dc99006a26e297 Mon Sep 17 00:00:00 2001 From: udkreddySomish Date: Mon, 2 Nov 2020 12:46:48 +0530 Subject: [PATCH 38/58] Implement old Market contract instead of rewriting whole code for new market conract --- contracts/MarketNew.sol | 641 ++++------------------------------------ 1 file changed, 59 insertions(+), 582 deletions(-) diff --git a/contracts/MarketNew.sol b/contracts/MarketNew.sol index 25f90927..29a51ed1 100644 --- a/contracts/MarketNew.sol +++ b/contracts/MarketNew.sol @@ -15,590 +15,67 @@ pragma solidity 0.5.7; -import "./external/openzeppelin-solidity/math/SafeMath.sol"; -import "./external/proxy/OwnedUpgradeabilityProxy.sol"; -import "./interfaces/IMarketUtility.sol"; -import "./interfaces/IToken.sol"; -import "./interfaces/ITokenController.sol"; -import "./interfaces/IMarketRegistry.sol"; - -contract MarketNew { - using SafeMath for *; - - enum PredictionStatus { - Live, - InSettlement, - Cooling, - InDispute, - Settled - } - - struct option - { - uint predictionPoints; - mapping(address => uint256) assetStaked; - mapping(address => uint256) assetLeveraged; - } - - struct MarketSettleData { - uint64 WinningOption; - uint64 settleTime; - } - - address constant ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE; - address constant marketFeedAddress = 0x5e2aa6b66531142bEAB830c385646F97fa03D80a; - address constant plotToken = 0xa626089A947Eadc8a782293B53fCf42247C71111; - - IMarketRegistry constant marketRegistry = IMarketRegistry(0x65Add15C5Ff3Abc069358AAe842dE13Ce92f3447); - ITokenController constant tokenController = ITokenController(0x3A3d9ca9d9b25AF1fF7eB9d8a1ea9f61B5892Ee9); - IMarketUtility constant marketUtility = IMarketUtility(0xCBc7df3b8C870C5CDE675AaF5Fd823E4209546D2); - - uint8 constant roundOfToNearest = 25; - uint constant totalOptions = 3; - uint constant MAX_LEVERAGE = 5; - uint constant ethCommissionPerc = 10; //with 2 decimals - uint constant plotCommissionPerc = 5; //with 2 decimals - bytes32 public constant marketCurrency = "ETH/USDT"; - - bool internal lockedForDispute; - address internal incentiveToken; - uint internal ethAmountToPool; - uint internal ethCommissionAmount; - uint internal plotCommissionAmount; - uint internal tokenAmountToPool; - uint internal incentiveToDistribute; - uint[] internal rewardToDistribute; - PredictionStatus internal predictionStatus; - - - struct UserData { - bool claimedReward; - bool predictedWithBlot; - bool multiplierApplied; - mapping(uint => uint) predictionPoints; - mapping(address => mapping(uint => uint)) assetStaked; - mapping(address => mapping(uint => uint)) LeverageAsset; - } - - struct MarketData { - uint64 startTime; - uint64 predictionTime; - uint64 neutralMinValue; - uint64 neutralMaxValue; - } - - MarketData public marketData; - MarketSettleData public marketSettleData; - - mapping(address => UserData) internal userData; - - mapping(uint=>option) public optionsAvailable; - - /** - * @dev Initialize the market. - * @param _startTime The time at which market will create. - * @param _predictionTime The time duration of market. - * @param _minValue The minimum value of neutral option range. - * @param _maxValue The maximum value of neutral option range. - */ - function initiate(uint64 _startTime, uint64 _predictionTime, uint64 _minValue, uint64 _maxValue) public payable { - OwnedUpgradeabilityProxy proxy = OwnedUpgradeabilityProxy(address(uint160(address(this)))); - require(msg.sender == proxy.proxyOwner(),"Sender is not proxy owner."); - require(marketData.startTime == 0, "Already initialized"); - require(_startTime.add(_predictionTime) > now); - marketData.startTime = _startTime; - marketData.predictionTime = _predictionTime; - - marketData.neutralMinValue = _minValue; - marketData.neutralMaxValue = _maxValue; - } - - /** - * @dev Place prediction on the available options of the market. - * @param _asset The asset used by user during prediction whether it is plotToken address or in ether. - * @param _predictionStake The amount staked by user at the time of prediction. - * @param _prediction The option on which user placed prediction. - * @param _leverage The leverage opted by user at the time of prediction. - */ - function placePrediction(address _asset, uint256 _predictionStake, uint256 _prediction,uint256 _leverage) public payable { - require(!marketRegistry.marketCreationPaused() && _prediction <= totalOptions && _leverage <= MAX_LEVERAGE); - require(now >= marketData.startTime && now <= marketExpireTime()); - - uint256 _commissionStake; - if(_asset == ETH_ADDRESS) { - require(_predictionStake == msg.value); - _commissionStake = _calculatePercentage(ethCommissionPerc, _predictionStake, 10000); - ethCommissionAmount = ethCommissionAmount.add(_commissionStake); - } else { - require(msg.value == 0); - if (_asset == plotToken){ - tokenController.transferFrom(plotToken, msg.sender, address(this), _predictionStake); - } else { - require(_asset == tokenController.bLOTToken()); - require(_leverage == MAX_LEVERAGE); - require(!userData[msg.sender].predictedWithBlot); - userData[msg.sender].predictedWithBlot = true; - tokenController.swapBLOT(msg.sender, address(this), _predictionStake); - _asset = plotToken; - } - _commissionStake = _calculatePercentage(plotCommissionPerc, _predictionStake, 10000); - plotCommissionAmount = plotCommissionAmount.add(_commissionStake); - } - _commissionStake = _predictionStake.sub(_commissionStake); - - - (uint predictionPoints, bool isMultiplierApplied) = calculatePredictionValue(_prediction, _commissionStake, _leverage, _asset); - if(isMultiplierApplied) { - userData[msg.sender].multiplierApplied = true; - } - require(predictionPoints > 0); - - _storePredictionData(_prediction, _commissionStake, _asset, _leverage, predictionPoints); - marketRegistry.setUserGlobalPredictionData(msg.sender,_predictionStake, predictionPoints, _asset, _prediction, _leverage); - } - - function calculatePredictionValue(uint _prediction, uint _predictionStake, uint _leverage, address _asset) internal view returns(uint predictionPoints, bool isMultiplierApplied) { - uint[] memory params = new uint[](11); - params[0] = _prediction; - params[1] = marketData.neutralMinValue; - params[2] = marketData.neutralMaxValue; - params[3] = marketData.startTime; - params[4] = marketExpireTime(); - (params[5], params[6]) = getTotalAssetsStaked(); - params[7] = optionsAvailable[_prediction].assetStaked[ETH_ADDRESS]; - params[8] = optionsAvailable[_prediction].assetStaked[plotToken]; - params[9] = _predictionStake; - params[10] = _leverage; - bool checkMultiplier; - if(!userData[msg.sender].multiplierApplied) { - checkMultiplier = true; - } - (predictionPoints, isMultiplierApplied) = marketUtility.calculatePredictionValue(params, _asset, msg.sender, marketFeedAddress, checkMultiplier); - - } - - function getTotalAssetsStaked() public view returns(uint256 ethStaked, uint256 plotStaked) { - for(uint256 i = 1; i<= totalOptions;i++) { - ethStaked = ethStaked.add(optionsAvailable[i].assetStaked[ETH_ADDRESS]); - plotStaked = plotStaked.add(optionsAvailable[i].assetStaked[plotToken]); - } - } - - function getTotalStakedValueInPLOT() public view returns(uint256) { - (uint256 ethStaked, uint256 plotStaked) = getTotalAssetsStaked(); - (, ethStaked) = marketUtility.getValueAndMultiplierParameters(ETH_ADDRESS, ethStaked); - return plotStaked.add(ethStaked); - } - - /** - * @dev Stores the prediction data. - * @param _prediction The option on which user place prediction. - * @param _predictionStake The amount staked by user at the time of prediction. - * @param _asset The asset used by user during prediction. - * @param _leverage The leverage opted by user during prediction. - * @param predictionPoints The positions user got during prediction. - */ - function _storePredictionData(uint _prediction, uint _predictionStake, address _asset, uint _leverage, uint predictionPoints) internal { - userData[msg.sender].predictionPoints[_prediction] = userData[msg.sender].predictionPoints[_prediction].add(predictionPoints); - userData[msg.sender].assetStaked[_asset][_prediction] = userData[msg.sender].assetStaked[_asset][_prediction].add(_predictionStake); - userData[msg.sender].LeverageAsset[_asset][_prediction] = userData[msg.sender].LeverageAsset[_asset][_prediction].add(_predictionStake.mul(_leverage)); - optionsAvailable[_prediction].predictionPoints = optionsAvailable[_prediction].predictionPoints.add(predictionPoints); - optionsAvailable[_prediction].assetStaked[_asset] = optionsAvailable[_prediction].assetStaked[_asset].add(_predictionStake); - optionsAvailable[_prediction].assetLeveraged[_asset] = optionsAvailable[_prediction].assetLeveraged[_asset].add(_predictionStake.mul(_leverage)); - } - - /** - * @dev Settle the market, setting the winning option - */ - function settleMarket() external { - (uint256 _value, uint256 _roundId) = marketUtility.getSettlemetPrice(marketFeedAddress, uint256(marketSettleTime())); - if(marketStatus() == PredictionStatus.InSettlement) { - _postResult(_value, _roundId); - } - } - - /** - * @dev Calculate the result of market. - * @param _value The current price of market currency. - */ - function _postResult(uint256 _value, uint256 _roundId) internal { - require(now >= marketSettleTime(),"Time not reached"); - require(_value > 0,"value should be greater than 0"); - uint riskPercentage; - ( , riskPercentage, , ) = marketUtility.getBasicMarketDetails(); - if(predictionStatus != PredictionStatus.InDispute) { - marketSettleData.settleTime = uint64(now); - } else { - delete marketSettleData.settleTime; - } - predictionStatus = PredictionStatus.Settled; - if(_value < marketData.neutralMinValue) { - marketSettleData.WinningOption = 1; - } else if(_value > marketData.neutralMaxValue) { - marketSettleData.WinningOption = 3; - } else { - marketSettleData.WinningOption = 2; - } - uint256 rewardPoolSharePerc = marketRegistry.getMarketCreatorRPoolSharePerc(address(this)); - uint[] memory totalReward = new uint256[](2); - uint[] memory marketCreatorIncentive = new uint256[](2); - if(optionsAvailable[marketSettleData.WinningOption].assetStaked[ETH_ADDRESS] > 0 || - optionsAvailable[marketSettleData.WinningOption].assetStaked[plotToken] > 0 - ){ - for(uint i=1;i <= totalOptions;i++){ - if(i!=marketSettleData.WinningOption) { - uint256 leveragedAsset = _calculatePercentage(riskPercentage, optionsAvailable[i].assetLeveraged[plotToken], 100); - totalReward[0] = totalReward[0].add(leveragedAsset); - leveragedAsset = _calculatePercentage(riskPercentage, optionsAvailable[i].assetLeveraged[ETH_ADDRESS], 100); - totalReward[1] = totalReward[1].add(leveragedAsset); - } - } - marketCreatorIncentive[0] = _calculatePercentage(rewardPoolSharePerc, totalReward[0], 10000); - marketCreatorIncentive[1] = _calculatePercentage(rewardPoolSharePerc, totalReward[1], 10000); - rewardToDistribute[0] = totalReward[0].sub(marketCreatorIncentive[0]); - rewardToDistribute[1] = totalReward[1].sub(marketCreatorIncentive[1]); - // rewardToDistribute = totalReward; - } else { - for(uint i=1;i <= totalOptions;i++){ +import "./Market.sol"; + +contract MarketNew is Market { + + /** + * @dev Calculate the result of market. + * @param _value The current price of market currency. + */ + function _postResult(uint256 _value, uint256 _roundId) internal { + require(now >= marketSettleTime(),"Time not reached"); + require(_value > 0,"value should be greater than 0"); + uint riskPercentage; + ( , riskPercentage, , ) = marketUtility.getBasicMarketDetails(); + if(predictionStatus != PredictionStatus.InDispute) { + marketSettleData.settleTime = uint64(now); + } else { + delete marketSettleData.settleTime; + } + predictionStatus = PredictionStatus.Settled; + if(_value < marketData.neutralMinValue) { + marketSettleData.WinningOption = 1; + } else if(_value > marketData.neutralMaxValue) { + marketSettleData.WinningOption = 3; + } else { + marketSettleData.WinningOption = 2; + } + uint256 rewardPoolSharePerc = marketRegistry.getMarketCreatorRPoolSharePerc(address(this)); + uint[] memory totalReward = new uint256[](2); + uint[] memory marketCreatorIncentive = new uint256[](2); + if(optionsAvailable[marketSettleData.WinningOption].assetStaked[ETH_ADDRESS] > 0 || + optionsAvailable[marketSettleData.WinningOption].assetStaked[plotToken] > 0 + ){ + for(uint i=1;i <= totalOptions;i++){ + if(i!=marketSettleData.WinningOption) { uint256 leveragedAsset = _calculatePercentage(riskPercentage, optionsAvailable[i].assetLeveraged[plotToken], 100); - tokenAmountToPool = tokenAmountToPool.add(leveragedAsset); + totalReward[0] = totalReward[0].add(leveragedAsset); leveragedAsset = _calculatePercentage(riskPercentage, optionsAvailable[i].assetLeveraged[ETH_ADDRESS], 100); - ethAmountToPool = ethAmountToPool.add(leveragedAsset); + totalReward[1] = totalReward[1].add(leveragedAsset); } - marketCreatorIncentive[0] = _calculatePercentage(rewardPoolSharePerc, tokenAmountToPool, 10000); - marketCreatorIncentive[1] = _calculatePercentage(rewardPoolSharePerc, ethAmountToPool, 10000); - tokenAmountToPool = tokenAmountToPool.sub(marketCreatorIncentive[0]); - ethAmountToPool = ethAmountToPool.sub(marketCreatorIncentive[1]); } - _transferAsset(ETH_ADDRESS, address(marketRegistry), ethAmountToPool.add(ethCommissionAmount).add(marketCreatorIncentive[1])); - _transferAsset(plotToken, address(marketRegistry), tokenAmountToPool.add(plotCommissionAmount).add(marketCreatorIncentive[0])); - delete ethCommissionAmount; - delete plotCommissionAmount; - marketRegistry.callMarketResultEvent(rewardToDistribute, marketCreatorIncentive, marketSettleData.WinningOption, _value, _roundId); - } - - function _calculatePercentage(uint256 _percent, uint256 _value, uint256 _divisor) internal pure returns(uint256) { - return _percent.mul(_value).div(_divisor); - } - - /** - * @dev Raise the dispute if wrong value passed at the time of market result declaration. - * @param proposedValue The proposed value of market currency. - * @param proposalTitle The title of proposal created by user. - * @param description The description of dispute. - * @param solutionHash The ipfs solution hash. - */ - function raiseDispute(uint256 proposedValue, string memory proposalTitle, string memory description, string memory solutionHash) public { - require(getTotalStakedValueInPLOT() > 0, "No participation"); - require(marketStatus() == PredictionStatus.Cooling); - uint _stakeForDispute = marketUtility.getDisputeResolutionParams(); - tokenController.transferFrom(plotToken, msg.sender, address(marketRegistry), _stakeForDispute); - lockedForDispute = true; - marketRegistry.createGovernanceProposal(proposalTitle, description, solutionHash, abi.encode(address(this), proposedValue), _stakeForDispute, msg.sender, ethAmountToPool, tokenAmountToPool, proposedValue); - delete ethAmountToPool; - delete tokenAmountToPool; - predictionStatus = PredictionStatus.InDispute; - } - - /** - * @dev Resolve the dispute - * @param accepted Flag mentioning if dispute is accepted or not - * @param finalResult The final correct value of market currency. - */ - function resolveDispute(bool accepted, uint256 finalResult) external payable { - require(msg.sender == address(marketRegistry) && marketStatus() == PredictionStatus.InDispute); - if(accepted) { - _postResult(finalResult, 0); - } - lockedForDispute = false; - predictionStatus = PredictionStatus.Settled; - } - - function sponsorIncentives(address _token, uint256 _value) external { - require(marketRegistry.isWhitelistedSponsor(msg.sender)); - require(marketStatus() <= PredictionStatus.InSettlement); - require(incentiveToken == address(0), "Already sponsored"); - incentiveToken = _token; - incentiveToDistribute = _value; - tokenController.transferFrom(_token, msg.sender, address(this), _value); - } - - - /** - * @dev Claim the return amount of the specified address. - * @param _user The address to query the claim return amount of. - * @return Flag, if 0:cannot claim, 1: Already Claimed, 2: Claimed - */ - function claimReturn(address payable _user) public returns(uint256) { - - if(lockedForDispute || marketStatus() != PredictionStatus.Settled || marketRegistry.marketCreationPaused()) { - return 0; - } - if(userData[_user].claimedReward) { - return 1; - } - userData[_user].claimedReward = true; - (uint[] memory _returnAmount, address[] memory _predictionAssets, uint _incentive, ) = getReturn(_user); - _transferAsset(plotToken, _user, _returnAmount[0]); - _transferAsset(ETH_ADDRESS, _user, _returnAmount[1]); - _transferAsset(incentiveToken, _user, _incentive); - marketRegistry.callClaimedEvent(_user, _returnAmount, _predictionAssets, _incentive, incentiveToken); - return 2; - } - - /** - * @dev Transfer the assets to specified address. - * @param _asset The asset transfer to the specific address. - * @param _recipient The address to transfer the asset of - * @param _amount The amount which is transfer. - */ - function _transferAsset(address _asset, address payable _recipient, uint256 _amount) internal { - if(_amount > 0) { - if(_asset == ETH_ADDRESS) { - _recipient.transfer(_amount); - } else { - require(IToken(_asset).transfer(_recipient, _amount)); - } - } - } - - /** - * @dev Get market settle time - * @return the time at which the market result will be declared - */ - function marketSettleTime() public view returns(uint64) { - if(marketSettleData.settleTime > 0) { - return marketSettleData.settleTime; - } - return uint64(marketData.startTime.add(marketData.predictionTime.mul(2))); - } - - /** - * @dev Get market expire time - * @return the time upto which user can place predictions in market - */ - function marketExpireTime() internal view returns(uint256) { - return marketData.startTime.add(marketData.predictionTime); - } - - /** - * @dev Get market cooldown time - * @return the time upto which user can raise the dispute after the market is settled - */ - function marketCoolDownTime() public view returns(uint256) { - return marketSettleData.settleTime.add(marketData.predictionTime.div(4)); - } - - /** - * @dev Get market Feed data - * @return market currency name - * @return market currency feed address - */ - function getMarketFeedData() public view returns(uint8, bytes32, address) { - return (roundOfToNearest, marketCurrency, marketFeedAddress); - } - - /** - * @dev Get estimated amount of prediction points for given inputs. - * @param _prediction The option on which user place prediction. - * @param _stakeValueInEth The amount staked by user. - * @param _leverage The leverage opted by user at the time of prediction. - * @return uint256 representing the prediction points. - */ - function estimatePredictionValue(uint _prediction, uint _stakeValueInEth, uint _leverage) public view returns(uint _predictionValue){ - (_predictionValue, ) = calculatePredictionValue(_prediction, _stakeValueInEth, _leverage, ETH_ADDRESS); - } - - /** - * @dev Gets the price of specific option. - * @param _prediction The option number to query the balance of. - * @return Price of the option. - */ - function getOptionPrice(uint _prediction) public view returns(uint) { - uint[] memory params = new uint[](9); - params[0] = _prediction; - params[1] = marketData.neutralMinValue; - params[2] = marketData.neutralMaxValue; - params[3] = marketData.startTime; - params[4] = marketExpireTime(); - (params[5], params[6]) = getTotalAssetsStaked(); - params[7] = optionsAvailable[_prediction].assetStaked[ETH_ADDRESS]; - params[8] = optionsAvailable[_prediction].assetStaked[plotToken]; - return marketUtility.calculateOptionPrice(params, marketFeedAddress); - } - - /** - * @dev Gets number of positions user got in prediction - * @param _user Address of user - * @param _option Option Id - */ - function getUserPredictionPoints(address _user, uint256 _option) external view returns(uint256) { - return userData[_user].predictionPoints[_option]; - } - - /** - * @dev Gets the market data. - * @return _marketCurrency bytes32 representing the currency or stock name of the market. - * @return minvalue uint[] memory representing the minimum range of all the options of the market. - * @return maxvalue uint[] memory representing the maximum range of all the options of the market. - * @return _optionPrice uint[] memory representing the option price of each option ranges of the market. - * @return _ethStaked uint[] memory representing the ether staked on each option ranges of the market. - * @return _plotStaked uint[] memory representing the plot staked on each option ranges of the market. - * @return _predictionTime uint representing the type of market. - * @return _expireTime uint representing the time at which market closes for prediction - * @return _predictionStatus uint representing the status of the market. - */ - function getData() public view returns - (bytes32 _marketCurrency,uint[] memory minvalue,uint[] memory maxvalue, - uint[] memory _optionPrice, uint[] memory _ethStaked, uint[] memory _plotStaked,uint _predictionTime,uint _expireTime, uint _predictionStatus){ - _marketCurrency = marketCurrency; - _predictionTime = marketData.predictionTime; - _expireTime =marketExpireTime(); - _predictionStatus = uint(marketStatus()); - minvalue = new uint[](totalOptions); - minvalue[1] = marketData.neutralMinValue; - minvalue[2] = marketData.neutralMaxValue.add(1); - maxvalue = new uint[](totalOptions); - maxvalue[0] = marketData.neutralMinValue.sub(1); - maxvalue[1] = marketData.neutralMaxValue; - maxvalue[2] = ~uint256(0); - - _optionPrice = new uint[](totalOptions); - _ethStaked = new uint[](totalOptions); - _plotStaked = new uint[](totalOptions); - for (uint i = 0; i < totalOptions; i++) { - _ethStaked[i] = optionsAvailable[i+1].assetStaked[ETH_ADDRESS]; - _plotStaked[i] = optionsAvailable[i+1].assetStaked[plotToken]; - _optionPrice[i] = getOptionPrice(i+1); - } - } - - /** - * @dev Gets the result of the market. - * @return uint256 representing the winning option of the market. - * @return uint256 Value of market currently at the time closing market. - * @return uint256 representing the positions of the winning option. - * @return uint[] memory representing the reward to be distributed. - * @return uint256 representing the Eth staked on winning option. - * @return uint256 representing the PLOT staked on winning option. - */ - function getMarketResults() public view returns(uint256, uint256, uint256[] memory, uint256, uint256) { - return (marketSettleData.WinningOption, optionsAvailable[marketSettleData.WinningOption].predictionPoints, rewardToDistribute, optionsAvailable[marketSettleData.WinningOption].assetStaked[ETH_ADDRESS], optionsAvailable[marketSettleData.WinningOption].assetStaked[plotToken]); - } - - - /** - * @dev Gets the return amount of the specified address. - * @param _user The address to specify the return of - * @return returnAmount uint[] memory representing the return amount. - * @return incentive uint[] memory representing the amount incentive. - * @return _incentiveTokens address[] memory representing the incentive tokens. - */ - function getReturn(address _user)public view returns (uint[] memory returnAmount, address[] memory _predictionAssets, uint incentive, address _incentiveToken){ - (uint256 ethStaked, uint256 plotStaked) = getTotalAssetsStaked(); - if(marketStatus() != PredictionStatus.Settled || ethStaked.add(plotStaked) ==0) { - return (returnAmount, _predictionAssets, incentive, incentiveToken); - } - _predictionAssets = new address[](2); - _predictionAssets[0] = plotToken; - _predictionAssets[1] = ETH_ADDRESS; - - uint256 _totalUserPredictionPoints = 0; - uint256 _totalPredictionPoints = 0; - (returnAmount, _totalUserPredictionPoints, _totalPredictionPoints) = _calculateUserReturn(_user); - incentive = _calculateIncentives(_totalUserPredictionPoints, _totalPredictionPoints); - if(userData[_user].predictionPoints[marketSettleData.WinningOption] > 0) { - returnAmount = _addUserReward(_user, returnAmount); - } - return (returnAmount, _predictionAssets, incentive, incentiveToken); - } - - /** - * @dev Get flags set for user - * @param _user User address - * @return Flag defining if user had availed multiplier - * @return Flag defining if user had predicted with bPLOT - */ - function getUserFlags(address _user) external view returns(bool, bool) { - return (userData[_user].multiplierApplied, userData[_user].predictedWithBlot); - } - - /** - * @dev Adds the reward in the total return of the specified address. - * @param _user The address to specify the return of. - * @param returnAmount The return amount. - * @return uint[] memory representing the return amount after adding reward. - */ - function _addUserReward(address _user, uint[] memory returnAmount) internal view returns(uint[] memory){ - uint reward; - for(uint j = 0; j< returnAmount.length; j++) { - reward = userData[_user].predictionPoints[marketSettleData.WinningOption].mul(rewardToDistribute[j]).div(optionsAvailable[marketSettleData.WinningOption].predictionPoints); - returnAmount[j] = returnAmount[j].add(reward); - } - return returnAmount; - } - - /** - * @dev Calculate the return of the specified address. - * @param _user The address to query the return of. - * @return _return uint[] memory representing the return amount owned by the passed address. - * @return _totalUserPredictionPoints uint representing the positions owned by the passed address. - * @return _totalPredictionPoints uint representing the total positions of winners. - */ - function _calculateUserReturn(address _user) internal view returns(uint[] memory _return, uint _totalUserPredictionPoints, uint _totalPredictionPoints){ - ( , uint riskPercentage, , ) = marketUtility.getBasicMarketDetails(); - _return = new uint256[](2); - for(uint i=1;i<=totalOptions;i++){ - _totalUserPredictionPoints = _totalUserPredictionPoints.add(userData[_user].predictionPoints[i]); - _totalPredictionPoints = _totalPredictionPoints.add(optionsAvailable[i].predictionPoints); - _return[0] = _callReturn(_return[0], _user, i, riskPercentage, plotToken); - _return[1] = _callReturn(_return[1], _user, i, riskPercentage, ETH_ADDRESS); - } - } - - /** - * @dev Calculates the incentives. - * @param _totalUserPredictionPoints The positions of user. - * @param _totalPredictionPoints The total positions of winners. - * @return incentive the calculated incentive. - */ - function _calculateIncentives(uint256 _totalUserPredictionPoints, uint256 _totalPredictionPoints) internal view returns(uint256 incentive){ - incentive = _totalUserPredictionPoints.mul(incentiveToDistribute.div(_totalPredictionPoints)); - } - - // /** - // * @dev Gets the pending return. - // * @param _user The address to specify the return of. - // * @return uint representing the pending return amount. - // */ - // function getPendingReturn(address _user) external view returns(uint[] memory returnAmount, address[] memory _predictionAssets, uint[] memory incentive, address[] memory _incentiveTokens){ - // if(userClaimedReward[_user]) return (0,0); - // return getReturn(_user); - // } - - /** - * @dev Calls the total return amount internally. - */ - function _callReturn(uint _return,address _user,uint i,uint riskPercentage, address _asset)internal view returns(uint){ - if(i == marketSettleData.WinningOption) { - riskPercentage = 0; - } - uint256 leveragedAsset = _calculatePercentage(riskPercentage, userData[_user].LeverageAsset[_asset][i], 100); - return _return.add(userData[_user].assetStaked[_asset][i].sub(leveragedAsset)); - } - - - /** - * @dev Gets the status of market. - * @return PredictionStatus representing the status of market. - */ - function marketStatus() internal view returns(PredictionStatus){ - if(predictionStatus == PredictionStatus.Live && now >= marketExpireTime()) { - return PredictionStatus.InSettlement; - } else if(predictionStatus == PredictionStatus.Settled && now <= marketCoolDownTime()) { - return PredictionStatus.Cooling; - } - return predictionStatus; - } - + marketCreatorIncentive[0] = _calculatePercentage(rewardPoolSharePerc, totalReward[0], 10000); + marketCreatorIncentive[1] = _calculatePercentage(rewardPoolSharePerc, totalReward[1], 10000); + rewardToDistribute[0] = totalReward[0].sub(marketCreatorIncentive[0]); + rewardToDistribute[1] = totalReward[1].sub(marketCreatorIncentive[1]); + // rewardToDistribute = totalReward; + } else { + for(uint i=1;i <= totalOptions;i++){ + uint256 leveragedAsset = _calculatePercentage(riskPercentage, optionsAvailable[i].assetLeveraged[plotToken], 100); + tokenAmountToPool = tokenAmountToPool.add(leveragedAsset); + leveragedAsset = _calculatePercentage(riskPercentage, optionsAvailable[i].assetLeveraged[ETH_ADDRESS], 100); + ethAmountToPool = ethAmountToPool.add(leveragedAsset); + } + marketCreatorIncentive[0] = _calculatePercentage(rewardPoolSharePerc, tokenAmountToPool, 10000); + marketCreatorIncentive[1] = _calculatePercentage(rewardPoolSharePerc, ethAmountToPool, 10000); + tokenAmountToPool = tokenAmountToPool.sub(marketCreatorIncentive[0]); + ethAmountToPool = ethAmountToPool.sub(marketCreatorIncentive[1]); + } + _transferAsset(ETH_ADDRESS, address(marketRegistry), ethAmountToPool.add(ethCommissionAmount).add(marketCreatorIncentive[1])); + _transferAsset(plotToken, address(marketRegistry), tokenAmountToPool.add(plotCommissionAmount).add(marketCreatorIncentive[0])); + delete ethCommissionAmount; + delete plotCommissionAmount; + marketRegistry.callMarketResultEvent(rewardToDistribute, marketCreatorIncentive, marketSettleData.WinningOption, _value, _roundId); + } } From 4e39b02bb7ff3536a7dbbe000c73d8ba6dc6c53b Mon Sep 17 00:00:00 2001 From: udkreddySomish Date: Mon, 2 Nov 2020 12:54:39 +0530 Subject: [PATCH 39/58] Added new function for calling market result event instead of updating the old one --- contracts/MarketNew.sol | 2 +- contracts/MarketRegistryNew.sol | 2 +- contracts/interfaces/IMarketRegistry.sol | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/contracts/MarketNew.sol b/contracts/MarketNew.sol index 29a51ed1..162f2d28 100644 --- a/contracts/MarketNew.sol +++ b/contracts/MarketNew.sol @@ -76,6 +76,6 @@ contract MarketNew is Market { _transferAsset(plotToken, address(marketRegistry), tokenAmountToPool.add(plotCommissionAmount).add(marketCreatorIncentive[0])); delete ethCommissionAmount; delete plotCommissionAmount; - marketRegistry.callMarketResultEvent(rewardToDistribute, marketCreatorIncentive, marketSettleData.WinningOption, _value, _roundId); + marketRegistry.callMarketResultEventAndSetIncentives(rewardToDistribute, marketCreatorIncentive, marketSettleData.WinningOption, _value, _roundId); } } diff --git a/contracts/MarketRegistryNew.sol b/contracts/MarketRegistryNew.sol index 5da8f852..1b2dae04 100644 --- a/contracts/MarketRegistryNew.sol +++ b/contracts/MarketRegistryNew.sol @@ -200,7 +200,7 @@ contract MarketRegistryNew is MarketRegistry { * @param winningOption The winning option of the market. * @param closeValue The closing value of the market currency. */ - function callMarketResultEvent(uint256[] calldata _totalReward, uint256[] calldata marketCreatorIncentive, uint256 winningOption, uint256 closeValue, uint _roundId) external { + function callMarketResultEventAndSetIncentives(uint256[] calldata _totalReward, uint256[] calldata marketCreatorIncentive, uint256 winningOption, uint256 closeValue, uint _roundId) external { require(isMarket(msg.sender)); marketCreationRewardData[msg.sender].plotIncentive = marketCreatorIncentive[0]; marketCreationRewardData[msg.sender].ethIncentive = marketCreatorIncentive[1]; diff --git a/contracts/interfaces/IMarketRegistry.sol b/contracts/interfaces/IMarketRegistry.sol index 4afcee50..60d8ec1e 100644 --- a/contracts/interfaces/IMarketRegistry.sol +++ b/contracts/interfaces/IMarketRegistry.sol @@ -23,7 +23,7 @@ contract IMarketRegistry { function transferAssets(address _asset, address _to, uint _amount) external; - function callMarketResultEvent(uint256[] calldata _totalReward, uint256[] calldata marketCreatorIncentive, uint256 winningOption, uint256 closeValue, uint _roundId) external; + function callMarketResultEventAndSetIncentives(uint256[] calldata _totalReward, uint256[] calldata marketCreatorIncentive, uint256 winningOption, uint256 closeValue, uint _roundId) external; function getUintParameters(bytes8 code) external view returns(bytes8 codeVal, uint256 value); From 95d6cb7a4de5ecb116878655743869ab666348b8 Mon Sep 17 00:00:00 2001 From: udkreddySomish Date: Mon, 2 Nov 2020 13:10:43 +0530 Subject: [PATCH 40/58] Added more testcases --- test/24_UpgradedCreationIncentive.test.js | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/test/24_UpgradedCreationIncentive.test.js b/test/24_UpgradedCreationIncentive.test.js index de6cae17..0f678d5c 100644 --- a/test/24_UpgradedCreationIncentive.test.js +++ b/test/24_UpgradedCreationIncentive.test.js @@ -543,6 +543,24 @@ contract("MarketUtility", async function([user1, user2, user3, user4, user5, use assert.equal((newBalanceEth/1e18).toFixed(2), (oldBalanceEth/1e18 + rewardPoolEth/100).toFixed(2)); }); + it('Should update MAXRPSP variable', async function() { + await updateParameter(20, 2, 'MAXRPSP', plotusNewInstance, 'configUint', 5000); + configData = await plotusNewInstance.getUintParameters(toHex('MAXRPSP')); + assert.equal(configData[1], 5000, 'Not updated'); + }); + + it('Should update MINRPSP variable', async function() { + await updateParameter(20, 2, 'MINRPSP', plotusNewInstance, 'configUint', 5000); + configData = await plotusNewInstance.getUintParameters(toHex('MINRPSP')); + assert.equal(configData[1], 5000, 'Not updated'); + }); + + it('Should update MINRPSP variable', async function() { + await updateParameter(20, 2, 'MINRPSP', plotusNewInstance, 'configUint', 5000); + configData = await plotusNewInstance.getUintParameters(toHex('MINRPSP')); + assert.equal(configData[1], 5000, 'Not updated'); + }); + it('Should update Chainlink gas aggrefgartor address', async function() { let clAgg = await MockChainLinkGasPriceAgg.new(); await updateParameter(21, 2, 'GASAGG', plotusNewInstance, 'configAddress', clAgg.address); From fe9b407143ec8617960838649a1effdad4a36aba Mon Sep 17 00:00:00 2001 From: udkreddySomish Date: Thu, 5 Nov 2020 19:08:00 +0530 Subject: [PATCH 41/58] Added a market leveraged participation threshold for reward pool share for market creator --- contracts/MarketNew.sol | 39 +++++++++++++++++++----- contracts/MarketRegistryNew.sol | 36 +++++++++++++--------- contracts/interfaces/IMarketRegistry.sol | 2 +- 3 files changed, 54 insertions(+), 23 deletions(-) diff --git a/contracts/MarketNew.sol b/contracts/MarketNew.sol index 162f2d28..bd526080 100644 --- a/contracts/MarketNew.sol +++ b/contracts/MarketNew.sol @@ -19,6 +19,25 @@ import "./Market.sol"; contract MarketNew is Market { + /** + * @dev Check if threshold reached for reward pool share percent for market creator. + * Calculate total leveraged amount staked in market value in ETH + * @param _rewardPoolShareThreshold Threshold for reward pool share + */ + function _checkIfThresholdReachedForRPS(uint256 _rewardPoolShareThreshold) internal view returns(bool) { + uint256 ethStaked; + uint256 plotStaked; + for(uint256 i = 1; i<= totalOptions;i++) { + ethStaked = ethStaked.add(optionsAvailable[i].assetLeveraged[ETH_ADDRESS]); + plotStaked = plotStaked.add(optionsAvailable[i].assetLeveraged[plotToken]); + } + ( , uint riskPercentage, , ) = marketUtility.getBasicMarketDetails(); + ethStaked = _calculatePercentage(riskPercentage, ethStaked, 100); + plotStaked = _calculatePercentage(riskPercentage, plotStaked, 100); + plotStaked = marketUtility.getAssetValueETH(plotToken, plotStaked); + return (plotStaked.add(ethStaked) > _rewardPoolShareThreshold); + } + /** * @dev Calculate the result of market. * @param _value The current price of market currency. @@ -41,7 +60,8 @@ contract MarketNew is Market { } else { marketSettleData.WinningOption = 2; } - uint256 rewardPoolSharePerc = marketRegistry.getMarketCreatorRPoolSharePerc(address(this)); + (uint256 rewardPoolSharePerc, uint256 rewardPoolShareThreshold) = marketRegistry.getMarketCreatorRPoolShareParams(address(this)); + bool _thresholdReached = _checkIfThresholdReachedForRPS(rewardPoolShareThreshold); uint[] memory totalReward = new uint256[](2); uint[] memory marketCreatorIncentive = new uint256[](2); if(optionsAvailable[marketSettleData.WinningOption].assetStaked[ETH_ADDRESS] > 0 || @@ -55,11 +75,12 @@ contract MarketNew is Market { totalReward[1] = totalReward[1].add(leveragedAsset); } } - marketCreatorIncentive[0] = _calculatePercentage(rewardPoolSharePerc, totalReward[0], 10000); - marketCreatorIncentive[1] = _calculatePercentage(rewardPoolSharePerc, totalReward[1], 10000); + if(_thresholdReached) { + marketCreatorIncentive[0] = _calculatePercentage(rewardPoolSharePerc, totalReward[0], 10000); + marketCreatorIncentive[1] = _calculatePercentage(rewardPoolSharePerc, totalReward[1], 10000); + } rewardToDistribute[0] = totalReward[0].sub(marketCreatorIncentive[0]); rewardToDistribute[1] = totalReward[1].sub(marketCreatorIncentive[1]); - // rewardToDistribute = totalReward; } else { for(uint i=1;i <= totalOptions;i++){ uint256 leveragedAsset = _calculatePercentage(riskPercentage, optionsAvailable[i].assetLeveraged[plotToken], 100); @@ -67,10 +88,12 @@ contract MarketNew is Market { leveragedAsset = _calculatePercentage(riskPercentage, optionsAvailable[i].assetLeveraged[ETH_ADDRESS], 100); ethAmountToPool = ethAmountToPool.add(leveragedAsset); } - marketCreatorIncentive[0] = _calculatePercentage(rewardPoolSharePerc, tokenAmountToPool, 10000); - marketCreatorIncentive[1] = _calculatePercentage(rewardPoolSharePerc, ethAmountToPool, 10000); - tokenAmountToPool = tokenAmountToPool.sub(marketCreatorIncentive[0]); - ethAmountToPool = ethAmountToPool.sub(marketCreatorIncentive[1]); + if(_thresholdReached) { + marketCreatorIncentive[0] = _calculatePercentage(rewardPoolSharePerc, tokenAmountToPool, 10000); + marketCreatorIncentive[1] = _calculatePercentage(rewardPoolSharePerc, ethAmountToPool, 10000); + tokenAmountToPool = tokenAmountToPool.sub(marketCreatorIncentive[0]); + ethAmountToPool = ethAmountToPool.sub(marketCreatorIncentive[1]); + } } _transferAsset(ETH_ADDRESS, address(marketRegistry), ethAmountToPool.add(ethCommissionAmount).add(marketCreatorIncentive[1])); _transferAsset(plotToken, address(marketRegistry), tokenAmountToPool.add(plotCommissionAmount).add(marketCreatorIncentive[0])); diff --git a/contracts/MarketRegistryNew.sol b/contracts/MarketRegistryNew.sol index 1b2dae04..8aaf3c23 100644 --- a/contracts/MarketRegistryNew.sol +++ b/contracts/MarketRegistryNew.sol @@ -38,6 +38,7 @@ contract MarketRegistryNew is MarketRegistry { uint256 maxRewardPoolPercForMC; uint256 minRewardPoolPercForMC; uint256 plotStakeForRewardPoolShare; + uint256 rewardPoolShareThreshold; mapping(address => MarketCreationRewardUserData) private marketCreationRewardUserData; //Of user mapping(address => MarketCreationRewardData) private marketCreationRewardData; //Of user @@ -52,9 +53,10 @@ contract MarketRegistryNew is MarketRegistry { require(msg.sender == marketInitiater); clGasPriceAggregator = IChainLinkOracle(_clGasPriceAggregator); maxGasPrice = 100 * 10**9; - maxRewardPoolPercForMC = 1000; // Raised by 2 decimals - minRewardPoolPercForMC = 100; // Raised by 2 decimals - plotStakeForRewardPoolShare = 50000 ether; + maxRewardPoolPercForMC = 500; // Raised by 2 decimals + minRewardPoolPercForMC = 50; // Raised by 2 decimals + plotStakeForRewardPoolShare = 25000 ether; + rewardPoolShareThreshold = 1 ether; } /** @@ -111,15 +113,15 @@ contract MarketRegistryNew is MarketRegistry { marketCreationRewardData[_market].rewardPoolSharePerc = Math.min( maxRewardPoolPercForMC, - minRewardPoolPercForMC + tokensLocked.div(plotStakeForRewardPoolShare).mul(100) + minRewardPoolPercForMC + tokensLocked.div(plotStakeForRewardPoolShare).mul(minRewardPoolPercForMC) ); } /** * @dev Get market reward pool share percent to be rewarded to market creator */ - function getMarketCreatorRPoolSharePerc(address _market) external view returns(uint256) { - return marketCreationRewardData[_market].rewardPoolSharePerc; + function getMarketCreatorRPoolShareParams(address _market) external view returns(uint256, uint256) { + return (marketCreationRewardData[_market].rewardPoolSharePerc, rewardPoolShareThreshold); } /** @@ -177,14 +179,16 @@ contract MarketRegistryNew is MarketRegistry { uint256 i; for(i = rewardData.lastClaimedIndex;i < len && count < _maxRecords; i++) { MarketCreationRewardData memory marketData = marketCreationRewardData[rewardData.marketsCreated[i]]; - ( , , , , , , , , uint _predictionStatus) = IMarket(rewardData.marketsCreated[i]).getData(); - if(_predictionStatus == uint(IMarket.PredictionStatus.Settled)) { - ethIncentive = ethIncentive.add(marketData.ethIncentive); - plotIncentive = plotIncentive.add(marketData.plotIncentive); - count++; - } else { - if(lastClaimed == len && (marketData.plotIncentive > 0 || marketData.ethIncentive > 0)) { - lastClaimed = i; + if(marketData.ethIncentive > 0 || marketData.plotIncentive > 0) { + ( , , , , , , , , uint _predictionStatus) = IMarket(rewardData.marketsCreated[i]).getData(); + if(_predictionStatus == uint(IMarket.PredictionStatus.Settled)) { + ethIncentive = ethIncentive.add(marketData.ethIncentive); + plotIncentive = plotIncentive.add(marketData.plotIncentive); + count++; + } else { + if(lastClaimed == len) { + lastClaimed = i; + } } } } @@ -233,6 +237,8 @@ contract MarketRegistryNew is MarketRegistry { minRewardPoolPercForMC = value; } else if(code == "PSFRPS") { // Reward Pool percent for market creator plotStakeForRewardPoolShare = value; + } else if(code == "RPSTH") { // Reward Pool percent for market creator + rewardPoolShareThreshold = value; } else { marketUtility.updateUintParameters(code, value); } @@ -253,6 +259,8 @@ contract MarketRegistryNew is MarketRegistry { value = minRewardPoolPercForMC; } else if(code == "PSFRPS") { value = plotStakeForRewardPoolShare; + } else if(code == "RPSTH") { + value = rewardPoolShareThreshold; } } diff --git a/contracts/interfaces/IMarketRegistry.sol b/contracts/interfaces/IMarketRegistry.sol index 60d8ec1e..2c379f0d 100644 --- a/contracts/interfaces/IMarketRegistry.sol +++ b/contracts/interfaces/IMarketRegistry.sol @@ -27,7 +27,7 @@ contract IMarketRegistry { function getUintParameters(bytes8 code) external view returns(bytes8 codeVal, uint256 value); - function getMarketCreatorRPoolSharePerc(address _market) external view returns(uint256); + function getMarketCreatorRPoolShareParams(address _market) external view returns(uint256, uint256); /** * @dev Initialize the PlotX. From c059a934fdcf7d0800b9217e63532c50293bc983 Mon Sep 17 00:00:00 2001 From: udkreddySomish Date: Fri, 6 Nov 2020 00:02:45 +0530 Subject: [PATCH 42/58] Fixed minor issue --- contracts/MarketNew.sol | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/contracts/MarketNew.sol b/contracts/MarketNew.sol index bd526080..13429ed7 100644 --- a/contracts/MarketNew.sol +++ b/contracts/MarketNew.sol @@ -79,8 +79,9 @@ contract MarketNew is Market { marketCreatorIncentive[0] = _calculatePercentage(rewardPoolSharePerc, totalReward[0], 10000); marketCreatorIncentive[1] = _calculatePercentage(rewardPoolSharePerc, totalReward[1], 10000); } - rewardToDistribute[0] = totalReward[0].sub(marketCreatorIncentive[0]); - rewardToDistribute[1] = totalReward[1].sub(marketCreatorIncentive[1]); + totalReward[0] = totalReward[0].sub(marketCreatorIncentive[0]); + totalReward[1] = totalReward[1].sub(marketCreatorIncentive[1]); + rewardToDistribute = totalReward; } else { for(uint i=1;i <= totalOptions;i++){ uint256 leveragedAsset = _calculatePercentage(riskPercentage, optionsAvailable[i].assetLeveraged[plotToken], 100); From b685a720cdb6f870c53951baf36b3750d1d5e6c4 Mon Sep 17 00:00:00 2001 From: udkreddySomish Date: Fri, 6 Nov 2020 00:02:57 +0530 Subject: [PATCH 43/58] Updated testcases --- test/24_UpgradedCreationIncentive.test.js | 277 +++++++++++++++++++--- 1 file changed, 238 insertions(+), 39 deletions(-) diff --git a/test/24_UpgradedCreationIncentive.test.js b/test/24_UpgradedCreationIncentive.test.js index 0f678d5c..5a1caa99 100644 --- a/test/24_UpgradedCreationIncentive.test.js +++ b/test/24_UpgradedCreationIncentive.test.js @@ -291,13 +291,17 @@ contract("MarketUtility", async function([user1, user2, user3, user4, user5, use value: "100000000000000000", from: user7, }); + await marketInstance.placePrediction(ethAddress, "1000000000000000000", 1, 5, { + value: "1000000000000000000", + from: user7, + }); await plotusToken.transfer(user7, toWei(10000)); await plotusToken.approve(tokenController.address, toWei(1000000000000000000), {from: user7}); await marketInstance.placePrediction(plotusToken.address, "100000000000000000000", 3, 5, { from: user7, }); let rewardPoolEth = 0.1; - let rewardPoolPlot = 100; + let rewardPoolPlot = 99.95; eventData = tx.logs[2].args; let gasUsed = eventData.gasUsed.toNumber(); let maxGas = await plotusNewInstance.getUintParameters(toHex("MAXGAS")); @@ -307,7 +311,7 @@ contract("MarketUtility", async function([user1, user2, user3, user4, user5, use let worthInPLOT = await marketConfig.getValueAndMultiplierParameters(ethAddress, costInETH + ""); incentivesGained = eventData.plotIncentive/1; let rewardPoolSharePerc = eventData.rewardPoolSharePerc; - assert.equal(rewardPoolSharePerc/1, 100) + assert.equal(rewardPoolSharePerc/1, 50) assert.equal(eventData.plotIncentive/1, worthInPLOT[1]/1); await increaseTime(10000); await marketInstance.settleMarket(); @@ -317,11 +321,59 @@ contract("MarketUtility", async function([user1, user2, user3, user4, user5, use tx = await plotusNewInstance.claimCreationRewardV2(100, {from:user2}); let newBalance = parseFloat(await plotusToken.balanceOf(user2)); let newBalanceEth = parseFloat(await web3.eth.getBalance(user2)); - assert.equal((newBalance/1e18).toFixed(2), (oldBalance/1e18 + incentivesGained/1e18 + rewardPoolPlot/100).toFixed(2)); - assert.equal((newBalanceEth/1e18).toFixed(2), (oldBalanceEth/1e18 + rewardPoolEth/100).toFixed(2)); + assert.equal((newBalance/1e18).toFixed(2), (oldBalance/1e18 + incentivesGained/1e18 + rewardPoolPlot*rewardPoolSharePerc/10000).toFixed(2)); + assert.equal((newBalanceEth/1e18).toFixed(2), (oldBalanceEth/1e18 + rewardPoolEth*rewardPoolSharePerc/10000).toFixed(2)); }); it("Scenario 2: Should be able to get more reward pool share of market if market creator had staked tokens", async function() { + await plotusToken.transfer(user9, toWei(25000)); + await plotusToken.approve(tokenController.address, "1000000000000000000000000", { from: user9 }); + await tokenController.lock("0x534d", toWei(25000), 86400 * 30, { from: user9 }); + await chainlinkGasAgg.setLatestAnswer(450000); + await increaseTime(3610); + let tx = await plotusNewInstance.createMarket(0,1, {gasPrice:450000, from:user9}); + let openMarkets = await plotusNewInstance.getOpenMarkets(); + let marketInstance = await MarketNew.at(openMarkets[0][1]); + await increaseTime(100); + await marketInstance.placePrediction(ethAddress, "100000000000000000", 3, 5, { + value: "100000000000000000", + from: user12, + }); + await marketInstance.placePrediction(ethAddress, "1000000000000000000", 1, 5, { + value: "1000000000000000000", + from: user12, + }); + await plotusToken.transfer(user7, toWei(10000)); + await plotusToken.approve(tokenController.address, toWei(1000000000000000000), {from: user7}); + await marketInstance.placePrediction(plotusToken.address, "100000000000000000000", 3, 5, { + from: user7, + }); + let rewardPoolEth = 0.1; + let rewardPoolPlot = 99.95; + eventData = tx.logs[2].args; + let gasUsed = eventData.gasUsed.toNumber(); + let maxGas = await plotusNewInstance.getUintParameters(toHex("MAXGAS")); + let gasPrice = Math.min(maxGas[1].toNumber(), 450000*1.25); + estimatedGasCost = gasPrice*gasUsed; + let costInETH = estimatedGasCost; + let worthInPLOT = await marketConfig.getValueAndMultiplierParameters(ethAddress, costInETH + ""); + incentivesGained = eventData.plotIncentive/1; + let rewardPoolSharePerc = eventData.rewardPoolSharePerc; + assert.equal(rewardPoolSharePerc/1, 100) + assert.equal(eventData.plotIncentive/1, worthInPLOT[1]/1); + await increaseTime(10000); + await marketInstance.settleMarket(); + await increaseTime(10000); + let oldBalance = parseFloat(await plotusToken.balanceOf(user9)); + let oldBalanceEth = parseFloat(await web3.eth.getBalance(user9)); + tx = await plotusNewInstance.claimCreationRewardV2(100, {from:user9}); + let newBalance = parseFloat(await plotusToken.balanceOf(user9)); + let newBalanceEth = parseFloat(await web3.eth.getBalance(user9)); + assert.equal((newBalance/1e18).toFixed(2), (oldBalance/1e18 + incentivesGained/1e18 + rewardPoolPlot*rewardPoolSharePerc/10000).toFixed(2)); + assert.equal((newBalanceEth/1e18).toFixed(2), (oldBalanceEth/1e18 + rewardPoolEth*rewardPoolSharePerc/10000).toFixed(2)); + }); + + it("Scenario 3: Should be able to get more reward pool share of market if market creator had staked tokens", async function() { await plotusToken.transfer(user3, toWei(50000)); await plotusToken.approve(tokenController.address, "1000000000000000000000000", { from: user3 }); await tokenController.lock("0x534d", toWei(50000), 86400 * 30, { from: user3 }); @@ -337,12 +389,16 @@ contract("MarketUtility", async function([user1, user2, user3, user4, user5, use }); await plotusToken.transfer(user7, toWei(10000)); await plotusToken.approve(tokenController.address, toWei(1000000000000000000), {from: user7}); - await marketInstance.placePrediction(plotusToken.address, "100000000000000000000", 3, 5, { + await marketInstance.placePrediction(plotusToken.address, "10000000000000000000", 3, 5, { from: user7, }); - let rewardPoolEth = 0.2; - let rewardPoolPlot = 200; - eventData = tx.logs[2].args; + let rewardPoolEth = 0.1; + let rewardPoolPlot = 9.95; + try { + eventData = tx.logs[2].args; + } catch(e) { + eventData = tx.logs[1].args; + } let gasUsed = eventData.gasUsed.toNumber(); let maxGas = await plotusNewInstance.getUintParameters(toHex("MAXGAS")); let gasPrice = Math.min(maxGas[1].toNumber(), 450000*1.25); @@ -351,7 +407,9 @@ contract("MarketUtility", async function([user1, user2, user3, user4, user5, use let worthInPLOT = await marketConfig.getValueAndMultiplierParameters(ethAddress, costInETH + ""); incentivesGained = eventData.plotIncentive/1; let rewardPoolSharePerc = eventData.rewardPoolSharePerc; - assert.equal(rewardPoolSharePerc/1, 200) + assert.equal(rewardPoolSharePerc/1, 150) + //As market participation is less than 1 ETH reward pool share will zero + rewardPoolSharePerc = 0; assert.equal(eventData.plotIncentive/1, worthInPLOT[1]/1); await increaseTime(10000); await marketInstance.settleMarket(); @@ -361,18 +419,22 @@ contract("MarketUtility", async function([user1, user2, user3, user4, user5, use tx = await plotusNewInstance.claimCreationRewardV2(100, {from:user3}); let newBalance = parseFloat(await plotusToken.balanceOf(user3)); let newBalanceEth = parseFloat(await web3.eth.getBalance(user3)); - assert.equal((newBalance/1e18).toFixed(2), (oldBalance/1e18 + incentivesGained/1e18 + rewardPoolPlot/100).toFixed(2)); - assert.equal((newBalanceEth/1e18).toFixed(2), (oldBalanceEth/1e18 + rewardPoolEth/100).toFixed(2)); + assert.equal((newBalance/1e18).toFixed(2), (oldBalance/1e18 + incentivesGained/1e18 + rewardPoolPlot*rewardPoolSharePerc/10000).toFixed(2)); + assert.equal((newBalanceEth/1e18).toFixed(2), (oldBalanceEth/1e18 + rewardPoolEth*rewardPoolSharePerc/10000).toFixed(2)); }); - it("Scenario 3: Should be able to get more reward pool share of market if market creator had staked tokens", async function() { - await plotusToken.transfer(user4, toWei(90000)); + it("Scenario 4: Should be able to get more reward pool share of market if market creator had staked tokens", async function() { + await plotusToken.transfer(user4, toWei(60000)); await plotusToken.approve(tokenController.address, "1000000000000000000000000", { from: user4 }); - await tokenController.lock("0x534d", toWei(50000), 86400 * 30, { from: user4 }); + await tokenController.lock("0x534d", toWei(60000), 86400 * 30, { from: user4 }); await chainlinkGasAgg.setLatestAnswer(450000); await increaseTime(3610); let tx = await plotusNewInstance.createMarket(0,1, {gasPrice:450000, from:user4}); - eventData = tx.logs[1].args; + try { + eventData = tx.logs[2].args; + } catch(e) { + eventData = tx.logs[1].args; + } let openMarkets = await plotusNewInstance.getOpenMarkets(); let marketInstance = await MarketNew.at(openMarkets[0][1]); await increaseTime(100); @@ -380,13 +442,17 @@ contract("MarketUtility", async function([user1, user2, user3, user4, user5, use value: "100000000000000000", from: user12, }); + await marketInstance.placePrediction(ethAddress, "1000000000000000000", 1, 5, { + value: "1000000000000000000", + from: user12, + }); await plotusToken.transfer(user7, toWei(10000)); await plotusToken.approve(tokenController.address, toWei(1000000000000000000), {from: user7}); await marketInstance.placePrediction(plotusToken.address, "100000000000000000000", 3, 5, { from: user7, }); - let rewardPoolEth = 0.2; - let rewardPoolPlot = 200; + let rewardPoolEth = 0.1; + let rewardPoolPlot = 99.95; let gasUsed = eventData.gasUsed.toNumber(); let maxGas = await plotusNewInstance.getUintParameters(toHex("MAXGAS")); let gasPrice = Math.min(maxGas[1].toNumber(), 450000*1.25); @@ -395,7 +461,7 @@ contract("MarketUtility", async function([user1, user2, user3, user4, user5, use let worthInPLOT = await marketConfig.getValueAndMultiplierParameters(ethAddress, costInETH + ""); incentivesGained = eventData.plotIncentive/1; let rewardPoolSharePerc = eventData.rewardPoolSharePerc; - assert.equal(rewardPoolSharePerc/1, 200) + assert.equal(rewardPoolSharePerc/1, 150) assert.equal(eventData.plotIncentive/1, worthInPLOT[1]/1); await increaseTime(10000); await marketInstance.settleMarket(); @@ -405,11 +471,11 @@ contract("MarketUtility", async function([user1, user2, user3, user4, user5, use tx = await plotusNewInstance.claimCreationRewardV2(100, {from:user4}); let newBalance = parseFloat(await plotusToken.balanceOf(user4)); let newBalanceEth = parseFloat(await web3.eth.getBalance(user4)); - assert.equal((newBalance/1e18).toFixed(2), (oldBalance/1e18 + incentivesGained/1e18 + rewardPoolPlot/100).toFixed(2)); - assert.equal((newBalanceEth/1e18).toFixed(2), (oldBalanceEth/1e18 + rewardPoolEth/100).toFixed(2)); + assert.equal((newBalance/1e18).toFixed(2), (oldBalance/1e18 + incentivesGained/1e18 + rewardPoolPlot*rewardPoolSharePerc/10000).toFixed(2)); + assert.equal((newBalanceEth/1e18).toFixed(2), (oldBalanceEth/1e18 + rewardPoolEth*rewardPoolSharePerc/10000).toFixed(2)); }); - it("Scenario 4: Should be able to get more reward pool share of market if market creator had staked tokens", async function() { + it("Scenario 5: Should be able to get more reward pool share of market if market creator had staked tokens", async function() { await plotusToken.transfer(user5, toWei(100000)); await plotusToken.approve(tokenController.address, "1000000000000000000000000", { from: user5 }); await tokenController.lock("0x534d", toWei(100000), 86400 * 30, { from: user5 }); @@ -428,8 +494,8 @@ contract("MarketUtility", async function([user1, user2, user3, user4, user5, use await marketInstance.placePrediction(plotusToken.address, "100000000000000000000", 3, 5, { from: user7, }); - let rewardPoolEth = 0.3; - let rewardPoolPlot = 300; + let rewardPoolEth = 0.1; + let rewardPoolPlot = 99.95; try { eventData = tx.logs[2].args; } catch(e) { @@ -443,7 +509,7 @@ contract("MarketUtility", async function([user1, user2, user3, user4, user5, use let worthInPLOT = await marketConfig.getValueAndMultiplierParameters(ethAddress, costInETH + ""); incentivesGained = eventData.plotIncentive/1; let rewardPoolSharePerc = eventData.rewardPoolSharePerc; - assert.equal(rewardPoolSharePerc/1, 300) + assert.equal(rewardPoolSharePerc/1, 250) assert.equal(eventData.plotIncentive/1, worthInPLOT[1]/1); await increaseTime(10000); await marketInstance.settleMarket(); @@ -453,11 +519,11 @@ contract("MarketUtility", async function([user1, user2, user3, user4, user5, use tx = await plotusNewInstance.claimCreationRewardV2(100, {from:user5}); let newBalance = parseFloat(await plotusToken.balanceOf(user5)); let newBalanceEth = parseFloat(await web3.eth.getBalance(user5)); - assert.equal((newBalance/1e18).toFixed(2), (oldBalance/1e18 + incentivesGained/1e18 + rewardPoolPlot/100).toFixed(2)); - assert.equal((newBalanceEth/1e18).toFixed(2), (oldBalanceEth/1e18 + rewardPoolEth/100).toFixed(2)); + assert.equal((newBalance/1e18).toFixed(2), (oldBalance/1e18 + incentivesGained/1e18 + rewardPoolPlot*rewardPoolSharePerc/10000).toFixed(2)); + assert.equal((newBalanceEth/1e18).toFixed(2), (oldBalanceEth/1e18 + rewardPoolEth*rewardPoolSharePerc/10000).toFixed(2)); }); - it("Scenario 5: Should be able to get more reward pool share of market if market creator had staked tokens", async function() { + it("Scenario 6: Should be able to get more reward pool share of market if market creator had staked tokens", async function() { await plotusToken.transfer(user6, toWei(150000)); await plotusToken.approve(tokenController.address, "1000000000000000000000000", { from: user6 }); await tokenController.lock("0x534d", toWei(150000), 86400 * 30, { from: user6 }); @@ -476,8 +542,8 @@ contract("MarketUtility", async function([user1, user2, user3, user4, user5, use await marketInstance.placePrediction(plotusToken.address, "100000000000000000000", 3, 5, { from: user7, }); - let rewardPoolEth = 0.4; - let rewardPoolPlot = 400; + let rewardPoolEth = 0.1; + let rewardPoolPlot = 99.95; try { eventData = tx.logs[2].args; } catch(e) { @@ -491,7 +557,7 @@ contract("MarketUtility", async function([user1, user2, user3, user4, user5, use let worthInPLOT = await marketConfig.getValueAndMultiplierParameters(ethAddress, costInETH + ""); incentivesGained = eventData.plotIncentive/1; let rewardPoolSharePerc = eventData.rewardPoolSharePerc; - assert.equal(rewardPoolSharePerc/1, 400) + assert.equal(rewardPoolSharePerc/1, 350) assert.equal(eventData.plotIncentive/1, worthInPLOT[1]/1); await increaseTime(10000); await marketInstance.settleMarket(); @@ -501,11 +567,11 @@ contract("MarketUtility", async function([user1, user2, user3, user4, user5, use tx = await plotusNewInstance.claimCreationRewardV2(100, {from:user6}); let newBalance = parseFloat(await plotusToken.balanceOf(user6)); let newBalanceEth = parseFloat(await web3.eth.getBalance(user6)); - assert.equal((newBalance/1e18).toFixed(2), (oldBalance/1e18 + incentivesGained/1e18 + rewardPoolPlot/100).toFixed(2)); - assert.equal((newBalanceEth/1e18).toFixed(2), (oldBalanceEth/1e18 + rewardPoolEth/100).toFixed(2)); + assert.equal((newBalance/1e18).toFixed(2), (oldBalance/1e18 + incentivesGained/1e18 + rewardPoolPlot*rewardPoolSharePerc/10000).toFixed(2)); + assert.equal((newBalanceEth/1e18).toFixed(2), (oldBalanceEth/1e18 + rewardPoolEth*rewardPoolSharePerc/10000).toFixed(2)); }); - it("Scenario 6: Should be able to get more reward pool share of market if market creator had staked tokens", async function() { + it("Scenario 7: Should be able to get more reward pool share of market if market creator had staked tokens", async function() { await plotusToken.transfer(user8, toWei(150000)); await plotusToken.approve(tokenController.address, "1000000000000000000000000", { from: user8 }); await tokenController.lock("0x534d", toWei(150000), 86400 * 30, { from: user8 }); @@ -529,7 +595,7 @@ contract("MarketUtility", async function([user1, user2, user3, user4, user5, use let worthInPLOT = await marketConfig.getValueAndMultiplierParameters(ethAddress, costInETH + ""); incentivesGained = eventData.plotIncentive/1; let rewardPoolSharePerc = eventData.rewardPoolSharePerc; - assert.equal(rewardPoolSharePerc/1, 400) + assert.equal(rewardPoolSharePerc/1, 350) assert.equal(eventData.plotIncentive/1, worthInPLOT[1]/1); await increaseTime(10000); await marketInstance.settleMarket(); @@ -539,8 +605,141 @@ contract("MarketUtility", async function([user1, user2, user3, user4, user5, use tx = await plotusNewInstance.claimCreationRewardV2(100, {from:user8}); let newBalance = parseFloat(await plotusToken.balanceOf(user8)); let newBalanceEth = parseFloat(await web3.eth.getBalance(user8)); - assert.equal((newBalance/1e18).toFixed(2), (oldBalance/1e18 + incentivesGained/1e18 + rewardPoolPlot/100).toFixed(2)); - assert.equal((newBalanceEth/1e18).toFixed(2), (oldBalanceEth/1e18 + rewardPoolEth/100).toFixed(2)); + assert.equal((newBalance/1e18).toFixed(2), (oldBalance/1e18 + incentivesGained/1e18 + rewardPoolPlot*rewardPoolSharePerc/10000).toFixed(2)); + assert.equal((newBalanceEth/1e18).toFixed(2), (oldBalanceEth/1e18 + rewardPoolEth*rewardPoolSharePerc/10000).toFixed(2)); + }); + + it("Raise Dispute and reject: Scenario 2: Should be able to get more reward pool share of market if market creator had staked tokens", async function() { + await plotusToken.transfer(user10, toWei(250000)); + await plotusToken.approve(tokenController.address, "1000000000000000000000000", { from: user10 }); + await tokenController.lock("0x534d", toWei(25000), 86400 * 30, { from: user10 }); + await chainlinkGasAgg.setLatestAnswer(450000); + await increaseTime(3610); + let tx = await plotusNewInstance.createMarket(0,1, {gasPrice:450000, from:user10}); + let openMarkets = await plotusNewInstance.getOpenMarkets(); + let marketInstance = await MarketNew.at(openMarkets[0][1]); + await increaseTime(100); + await marketInstance.placePrediction(ethAddress, "100000000000000000", 3, 5, { + value: "100000000000000000", + from: user12, + }); + await marketInstance.placePrediction(ethAddress, "1000000000000000000", 1, 5, { + value: "1000000000000000000", + from: user12, + }); + await plotusToken.transfer(user7, toWei(10000)); + await plotusToken.approve(tokenController.address, toWei(1000000000000000000), {from: user7}); + await marketInstance.placePrediction(plotusToken.address, "100000000000000000000", 3, 5, { + from: user7, + }); + + let rewardPoolEth = 0.1; + let rewardPoolPlot = 99.95; + try { + eventData = tx.logs[2].args; + } catch(e) { + eventData = tx.logs[1].args; + } + let gasUsed = eventData.gasUsed.toNumber(); + let maxGas = await plotusNewInstance.getUintParameters(toHex("MAXGAS")); + let gasPrice = Math.min(maxGas[1].toNumber(), 450000*1.25); + estimatedGasCost = gasPrice*gasUsed; + let costInETH = estimatedGasCost; + let worthInPLOT = await marketConfig.getValueAndMultiplierParameters(ethAddress, costInETH + ""); + incentivesGained = eventData.plotIncentive/1; + let rewardPoolSharePerc = eventData.rewardPoolSharePerc; + assert.equal(rewardPoolSharePerc/1, 100) + assert.equal(eventData.plotIncentive/1, worthInPLOT[1]/1); + await increaseTime(10000); + await marketInstance.settleMarket(); + let proposalId = await governance.getProposalLength(); + await marketInstance.raiseDispute(1400000000000,"raise dispute","this is description","this is solution hash", { from: user10 }); + await increaseTime(604800); + await governance.closeProposal(proposalId); + await increaseTime(10000); + let oldBalance = parseFloat(await plotusToken.balanceOf(user10)); + let oldBalanceEth = parseFloat(await web3.eth.getBalance(user10)); + tx = await plotusNewInstance.claimCreationRewardV2(100, {from:user10}); + let newBalance = parseFloat(await plotusToken.balanceOf(user10)); + let newBalanceEth = parseFloat(await web3.eth.getBalance(user10)); + assert.equal((newBalance/1e18).toFixed(2), (oldBalance/1e18 + incentivesGained/1e18 + rewardPoolPlot*rewardPoolSharePerc/10000).toFixed(2)); + assert.equal((newBalanceEth/1e18).toFixed(2), (oldBalanceEth/1e18 + rewardPoolEth*rewardPoolSharePerc/10000).toFixed(2)); + }); + + it("Raise Dispute and pass: Scenario 2: Should be able to get more reward pool share of market if market creator had staked tokens", async function() { + await plotusToken.transfer(user10, toWei(250000)); + await plotusToken.approve(tokenController.address, "1000000000000000000000000", { from: user10 }); + await tokenController.extendLock("0x534d", 86400 * 30, { from: user10 }); + await chainlinkGasAgg.setLatestAnswer(450000); + await increaseTime(3610); + let tx = await plotusNewInstance.createMarket(0,1, {gasPrice:450000, from:user10}); + let openMarkets = await plotusNewInstance.getOpenMarkets(); + let marketInstance = await MarketNew.at(openMarkets[0][1]); + await increaseTime(100); + await marketInstance.placePrediction(ethAddress, "100000000000000000", 3, 5, { + value: "100000000000000000", + from: user12, + }); + await marketInstance.placePrediction(ethAddress, "1000000000000000000", 1, 5, { + value: "1000000000000000000", + from: user12, + }); + await plotusToken.transfer(user7, toWei(10000)); + await plotusToken.approve(tokenController.address, toWei(1000000000000000000), {from: user7}); + await marketInstance.placePrediction(plotusToken.address, "100000000000000000000", 3, 5, { + from: user7, + }); + await marketInstance.placePrediction(plotusToken.address, "100000000000000000000", 1, 5, { + from: user7, + }); + await increaseTime(10000); + await marketInstance.settleMarket(); + let proposalId = await governance.getProposalLength(); + await marketInstance.raiseDispute("9999999000000000","raise dispute","this is description","this is solution hash", { from: user10 }); + await plotusToken.approve(tokenController.address, "100000000000000000000000",{from : user2}); + await plotusToken.transfer(user2, toWei(30000)); + await tokenController.lock("0x4452","30000000000000000000000",(86400*20),{from : user2}); + + await plotusToken.approve(tokenController.address, "100000000000000000000000",{from : user3}); + await plotusToken.transfer(user3, toWei(30000)); + await tokenController.lock("0x4452","30000000000000000000000",(86400*20),{from : user3}); + + await plotusToken.approve(tokenController.address, "100000000000000000000000",{from : user4}); + await plotusToken.transfer(user4, toWei(30000)); + await tokenController.lock("0x4452","30000000000000000000000",(86400*20),{from : user4}); + + await governance.submitVote(proposalId, 1, {from:user2}); + await governance.submitVote(proposalId, 1, {from:user3}); + await governance.submitVote(proposalId, 1, {from:user4}); + await increaseTime(604800); + await governance.closeProposal(proposalId); + await increaseTime(10000); + + let rewardPoolEth = 0.99; + let rewardPoolPlot = 99.95; + try { + eventData = tx.logs[2].args; + } catch(e) { + eventData = tx.logs[1].args; + } + let gasUsed = eventData.gasUsed.toNumber(); + let maxGas = await plotusNewInstance.getUintParameters(toHex("MAXGAS")); + let gasPrice = Math.min(maxGas[1].toNumber(), 450000*1.25); + estimatedGasCost = gasPrice*gasUsed; + let costInETH = estimatedGasCost; + let worthInPLOT = await marketConfig.getValueAndMultiplierParameters(ethAddress, costInETH + ""); + incentivesGained = eventData.plotIncentive/1; + let rewardPoolSharePerc = eventData.rewardPoolSharePerc; + assert.equal(rewardPoolSharePerc/1, 100) + assert.equal(eventData.plotIncentive/1, worthInPLOT[1]/1); + + let oldBalance = parseFloat(await plotusToken.balanceOf(user10)); + let oldBalanceEth = parseFloat(await web3.eth.getBalance(user10)); + tx = await plotusNewInstance.claimCreationRewardV2(100, {from:user10}); + let newBalance = parseFloat(await plotusToken.balanceOf(user10)); + let newBalanceEth = parseFloat(await web3.eth.getBalance(user10)); + assert.equal((newBalance/1e18).toFixed(2), (oldBalance/1e18 + incentivesGained/1e18 + rewardPoolPlot*rewardPoolSharePerc/10000).toFixed(2)); + assert.equal((newBalanceEth/1e18).toFixed(2), (oldBalanceEth/1e18 + rewardPoolEth*rewardPoolSharePerc/10000).toFixed(2)); }); it('Should update MAXRPSP variable', async function() { @@ -555,9 +754,9 @@ contract("MarketUtility", async function([user1, user2, user3, user4, user5, use assert.equal(configData[1], 5000, 'Not updated'); }); - it('Should update MINRPSP variable', async function() { - await updateParameter(20, 2, 'MINRPSP', plotusNewInstance, 'configUint', 5000); - configData = await plotusNewInstance.getUintParameters(toHex('MINRPSP')); + it('Should update RPSTH variable', async function() { + await updateParameter(20, 2, 'RPSTH', plotusNewInstance, 'configUint', 5000); + configData = await plotusNewInstance.getUintParameters(toHex('RPSTH')); assert.equal(configData[1], 5000, 'Not updated'); }); From bc50cd3ed3115cfa37298bed5b62403c35aa4c9b Mon Sep 17 00:00:00 2001 From: udkreddySomish Date: Fri, 6 Nov 2020 10:56:54 +0530 Subject: [PATCH 44/58] Fixed broken testcases in coverage run --- test/01_hourlyMarketOptionPrice.js | 2 +- test/24_UpgradedCreationIncentive.test.js | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/test/01_hourlyMarketOptionPrice.js b/test/01_hourlyMarketOptionPrice.js index 38b6c28f..ea171c1e 100644 --- a/test/01_hourlyMarketOptionPrice.js +++ b/test/01_hourlyMarketOptionPrice.js @@ -612,7 +612,7 @@ contract("Market", async function([user1, user2, user3, user4, user5, user6, use //console.log("Round off LOT price of option3", optionPriceLOT3 / 1000); assert.equal(parseFloat(Math.floor((optionPriceETH1 / 1000) * 100) / 100), 0.13); - assert.equal(parseFloat(Math.floor((optionPriceETH2 / 1000) * 100) / 100), 0.15); + assert.equal((optionPriceETH2 / 1000).toFixed(2), (0.15).toFixed(2)); assert.equal((optionPriceETH3 / 1000).toFixed(2), (0.078).toFixed(2)); assert.equal(parseInt(optionPriceLOT1 / 1000), parseInt(11)); expect(optionPriceLOT2 / 1000).to.be.closeTo(12.9, 13.3);//12.917 diff --git a/test/24_UpgradedCreationIncentive.test.js b/test/24_UpgradedCreationIncentive.test.js index 5a1caa99..d4689eb8 100644 --- a/test/24_UpgradedCreationIncentive.test.js +++ b/test/24_UpgradedCreationIncentive.test.js @@ -32,7 +32,7 @@ var incentivesGained = 0; const ethAddress = "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE"; var nullAddress = "0x0000000000000000000000000000"; -contract("MarketUtility", async function([user1, user2, user3, user4, user5, user6, user7, user8, user9, user10, user11, user12]) { +contract("MarketUtility", async function([user1, user2, user3, user4, user5, user6, user7, user8, user9, user10, user11, user12, user13]) { let masterInstance, plotusToken, marketConfig, @@ -337,11 +337,11 @@ contract("MarketUtility", async function([user1, user2, user3, user4, user5, use await increaseTime(100); await marketInstance.placePrediction(ethAddress, "100000000000000000", 3, 5, { value: "100000000000000000", - from: user12, + from: user13, }); await marketInstance.placePrediction(ethAddress, "1000000000000000000", 1, 5, { value: "1000000000000000000", - from: user12, + from: user13, }); await plotusToken.transfer(user7, toWei(10000)); await plotusToken.approve(tokenController.address, toWei(1000000000000000000), {from: user7}); From abd3e1be4d263c0cb515d069644c2a2f25530478 Mon Sep 17 00:00:00 2001 From: udkreddySomish Date: Fri, 6 Nov 2020 11:28:31 +0530 Subject: [PATCH 45/58] Fixed broken testcases --- test/01_hourlyMarketOptionPrice.js | 2 +- test/24_UpgradedCreationIncentive.test.js | 24 +++++++++++------------ 2 files changed, 12 insertions(+), 14 deletions(-) diff --git a/test/01_hourlyMarketOptionPrice.js b/test/01_hourlyMarketOptionPrice.js index ea171c1e..59001450 100644 --- a/test/01_hourlyMarketOptionPrice.js +++ b/test/01_hourlyMarketOptionPrice.js @@ -592,7 +592,7 @@ contract("Market", async function([user1, user2, user3, user4, user5, user6, use from: user2, }); - await increaseTime(1211); + await increaseTime(1210); let currentPriceAfter_af = await MockchainLinkInstance.latestAnswer(); //console.log(currentPriceAfter_af / 1); let priceOption1_af = await marketInstance.getOptionPrice(1); diff --git a/test/24_UpgradedCreationIncentive.test.js b/test/24_UpgradedCreationIncentive.test.js index d4689eb8..16499566 100644 --- a/test/24_UpgradedCreationIncentive.test.js +++ b/test/24_UpgradedCreationIncentive.test.js @@ -326,15 +326,14 @@ contract("MarketUtility", async function([user1, user2, user3, user4, user5, use }); it("Scenario 2: Should be able to get more reward pool share of market if market creator had staked tokens", async function() { - await plotusToken.transfer(user9, toWei(25000)); - await plotusToken.approve(tokenController.address, "1000000000000000000000000", { from: user9 }); - await tokenController.lock("0x534d", toWei(25000), 86400 * 30, { from: user9 }); + await plotusToken.transfer(user12, toWei(25000)); + await plotusToken.approve(tokenController.address, "1000000000000000000000000", { from: user12 }); + await tokenController.lock("0x534d", toWei(25000), 86400 * 30, { from: user12 }); await chainlinkGasAgg.setLatestAnswer(450000); await increaseTime(3610); - let tx = await plotusNewInstance.createMarket(0,1, {gasPrice:450000, from:user9}); + let tx = await plotusNewInstance.createMarket(0,1, {gasPrice:450000, from:user12}); let openMarkets = await plotusNewInstance.getOpenMarkets(); let marketInstance = await MarketNew.at(openMarkets[0][1]); - await increaseTime(100); await marketInstance.placePrediction(ethAddress, "100000000000000000", 3, 5, { value: "100000000000000000", from: user13, @@ -364,11 +363,11 @@ contract("MarketUtility", async function([user1, user2, user3, user4, user5, use await increaseTime(10000); await marketInstance.settleMarket(); await increaseTime(10000); - let oldBalance = parseFloat(await plotusToken.balanceOf(user9)); - let oldBalanceEth = parseFloat(await web3.eth.getBalance(user9)); - tx = await plotusNewInstance.claimCreationRewardV2(100, {from:user9}); - let newBalance = parseFloat(await plotusToken.balanceOf(user9)); - let newBalanceEth = parseFloat(await web3.eth.getBalance(user9)); + let oldBalance = parseFloat(await plotusToken.balanceOf(user12)); + let oldBalanceEth = parseFloat(await web3.eth.getBalance(user12)); + tx = await plotusNewInstance.claimCreationRewardV2(100, {from:user12}); + let newBalance = parseFloat(await plotusToken.balanceOf(user12)); + let newBalanceEth = parseFloat(await web3.eth.getBalance(user12)); assert.equal((newBalance/1e18).toFixed(2), (oldBalance/1e18 + incentivesGained/1e18 + rewardPoolPlot*rewardPoolSharePerc/10000).toFixed(2)); assert.equal((newBalanceEth/1e18).toFixed(2), (oldBalanceEth/1e18 + rewardPoolEth*rewardPoolSharePerc/10000).toFixed(2)); }); @@ -437,14 +436,13 @@ contract("MarketUtility", async function([user1, user2, user3, user4, user5, use } let openMarkets = await plotusNewInstance.getOpenMarkets(); let marketInstance = await MarketNew.at(openMarkets[0][1]); - await increaseTime(100); await marketInstance.placePrediction(ethAddress, "100000000000000000", 3, 5, { value: "100000000000000000", - from: user12, + from: user13, }); await marketInstance.placePrediction(ethAddress, "1000000000000000000", 1, 5, { value: "1000000000000000000", - from: user12, + from: user13, }); await plotusToken.transfer(user7, toWei(10000)); await plotusToken.approve(tokenController.address, toWei(1000000000000000000), {from: user7}); From 7ce214fd2b334748970f4c2e08fa9af6e96393c7 Mon Sep 17 00:00:00 2001 From: udkreddySomish Date: Fri, 6 Nov 2020 11:58:51 +0530 Subject: [PATCH 46/58] Fixed broken testcases --- test/01_hourlyMarketOptionPrice.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/01_hourlyMarketOptionPrice.js b/test/01_hourlyMarketOptionPrice.js index 59001450..320cae3a 100644 --- a/test/01_hourlyMarketOptionPrice.js +++ b/test/01_hourlyMarketOptionPrice.js @@ -612,7 +612,7 @@ contract("Market", async function([user1, user2, user3, user4, user5, user6, use //console.log("Round off LOT price of option3", optionPriceLOT3 / 1000); assert.equal(parseFloat(Math.floor((optionPriceETH1 / 1000) * 100) / 100), 0.13); - assert.equal((optionPriceETH2 / 1000).toFixed(2), (0.15).toFixed(2)); + expect(optionPriceETH2 / 1000).to.be.closeTo(0.15, 0.16);//0.15 assert.equal((optionPriceETH3 / 1000).toFixed(2), (0.078).toFixed(2)); assert.equal(parseInt(optionPriceLOT1 / 1000), parseInt(11)); expect(optionPriceLOT2 / 1000).to.be.closeTo(12.9, 13.3);//12.917 From 0e74370a093b072e9e23a22272813c2396be26fd Mon Sep 17 00:00:00 2001 From: udkreddySomish Date: Sun, 8 Nov 2020 14:45:00 +0530 Subject: [PATCH 47/58] Fixed issue while user claiming market creation rewards --- contracts/MarketRegistryNew.sol | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/contracts/MarketRegistryNew.sol b/contracts/MarketRegistryNew.sol index 8aaf3c23..388a8a9c 100644 --- a/contracts/MarketRegistryNew.sol +++ b/contracts/MarketRegistryNew.sol @@ -178,12 +178,14 @@ contract MarketRegistryNew is MarketRegistry { uint256 count; uint256 i; for(i = rewardData.lastClaimedIndex;i < len && count < _maxRecords; i++) { - MarketCreationRewardData memory marketData = marketCreationRewardData[rewardData.marketsCreated[i]]; + MarketCreationRewardData storage marketData = marketCreationRewardData[rewardData.marketsCreated[i]]; if(marketData.ethIncentive > 0 || marketData.plotIncentive > 0) { ( , , , , , , , , uint _predictionStatus) = IMarket(rewardData.marketsCreated[i]).getData(); if(_predictionStatus == uint(IMarket.PredictionStatus.Settled)) { ethIncentive = ethIncentive.add(marketData.ethIncentive); plotIncentive = plotIncentive.add(marketData.plotIncentive); + delete marketData.ethIncentive; + delete marketData.plotIncentive; count++; } else { if(lastClaimed == len) { From 00adefc4d89fb7d506ca7a3517272a41c948f9a6 Mon Sep 17 00:00:00 2001 From: udkreddySomish Date: Tue, 10 Nov 2020 16:49:10 +0530 Subject: [PATCH 48/58] Added a function to get users pending market creation rewards --- contracts/MarketRegistryNew.sol | 29 +++++++++++++++++++++++ test/24_UpgradedCreationIncentive.test.js | 5 ++++ 2 files changed, 34 insertions(+) diff --git a/contracts/MarketRegistryNew.sol b/contracts/MarketRegistryNew.sol index 388a8a9c..c96114fc 100644 --- a/contracts/MarketRegistryNew.sol +++ b/contracts/MarketRegistryNew.sol @@ -200,6 +200,35 @@ contract MarketRegistryNew is MarketRegistry { rewardData.lastClaimedIndex = lastClaimed; } + /** + * @dev function to get pending reward of user for initiating market creation calls as per the new incetive calculations + * @return plotIncentive Incentives given for creating market as per the gas consumed + * @return pendingPLOTReward PLOT Reward pool share of markets created by user + * @return pendingETHReward ETH Reward pool share of markets created by user + */ + function getPendingMarketCreationRewards() external view returns(uint256 plotIncentive, uint256 pendingPLOTReward, uint256 pendingETHReward){ + plotIncentive = marketCreationRewardUserData[msg.sender].incentives; + (pendingETHReward, pendingPLOTReward) = _getPendingRewardPoolIncentives(); + } + + /** + * @dev internal function to calculate market reward pool share incentives for market creator + */ + function _getPendingRewardPoolIncentives() internal view returns(uint256 ethIncentive, uint256 plotIncentive) { + MarketCreationRewardUserData memory rewardData = marketCreationRewardUserData[msg.sender]; + uint256 len = rewardData.marketsCreated.length; + for(uint256 i = rewardData.lastClaimedIndex;i < len; i++) { + MarketCreationRewardData memory marketData = marketCreationRewardData[rewardData.marketsCreated[i]]; + if(marketData.ethIncentive > 0 || marketData.plotIncentive > 0) { + ( , , , , , , , , uint _predictionStatus) = IMarket(rewardData.marketsCreated[i]).getData(); + if(_predictionStatus == uint(IMarket.PredictionStatus.Settled)) { + ethIncentive = ethIncentive.add(marketData.ethIncentive); + plotIncentive = plotIncentive.add(marketData.plotIncentive); + } + } + } + } + /** * @dev Emits the MarketResult event. * @param _totalReward The amount of reward to be distribute. diff --git a/test/24_UpgradedCreationIncentive.test.js b/test/24_UpgradedCreationIncentive.test.js index 16499566..95b5793d 100644 --- a/test/24_UpgradedCreationIncentive.test.js +++ b/test/24_UpgradedCreationIncentive.test.js @@ -673,6 +673,7 @@ contract("MarketUtility", async function([user1, user2, user3, user4, user5, use let tx = await plotusNewInstance.createMarket(0,1, {gasPrice:450000, from:user10}); let openMarkets = await plotusNewInstance.getOpenMarkets(); let marketInstance = await MarketNew.at(openMarkets[0][1]); + let pendingRewards = await plotusNewInstance.getPendingMarketCreationRewards(); await increaseTime(100); await marketInstance.placePrediction(ethAddress, "100000000000000000", 3, 5, { value: "100000000000000000", @@ -691,6 +692,7 @@ contract("MarketUtility", async function([user1, user2, user3, user4, user5, use from: user7, }); await increaseTime(10000); + pendingRewards = await plotusNewInstance.getPendingMarketCreationRewards(); await marketInstance.settleMarket(); let proposalId = await governance.getProposalLength(); await marketInstance.raiseDispute("9999999000000000","raise dispute","this is description","this is solution hash", { from: user10 }); @@ -733,9 +735,12 @@ contract("MarketUtility", async function([user1, user2, user3, user4, user5, use let oldBalance = parseFloat(await plotusToken.balanceOf(user10)); let oldBalanceEth = parseFloat(await web3.eth.getBalance(user10)); + pendingRewards = await plotusNewInstance.getPendingMarketCreationRewards({from:user10}); tx = await plotusNewInstance.claimCreationRewardV2(100, {from:user10}); let newBalance = parseFloat(await plotusToken.balanceOf(user10)); let newBalanceEth = parseFloat(await web3.eth.getBalance(user10)); + assert.equal((newBalance/1e18).toFixed(2), (oldBalance/1e18 + pendingRewards[0]/1e18 + pendingRewards[1]/1e18).toFixed(2)); + assert.equal((newBalanceEth/1e18).toFixed(2), (oldBalanceEth/1e18 + pendingRewards[2]/1e18).toFixed(2)); assert.equal((newBalance/1e18).toFixed(2), (oldBalance/1e18 + incentivesGained/1e18 + rewardPoolPlot*rewardPoolSharePerc/10000).toFixed(2)); assert.equal((newBalanceEth/1e18).toFixed(2), (oldBalanceEth/1e18 + rewardPoolEth*rewardPoolSharePerc/10000).toFixed(2)); }); From e2a0e849f3a1ec29fe204b77031f3090f0df4373 Mon Sep 17 00:00:00 2001 From: udkreddySomish Date: Wed, 11 Nov 2020 16:48:33 +0530 Subject: [PATCH 49/58] Added event market creator reward pool share details --- contracts/MarketRegistryNew.sol | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/contracts/MarketRegistryNew.sol b/contracts/MarketRegistryNew.sol index c96114fc..bfda4449 100644 --- a/contracts/MarketRegistryNew.sol +++ b/contracts/MarketRegistryNew.sol @@ -33,6 +33,7 @@ contract MarketRegistryNew is MarketRegistry { uint ethIncentive; uint plotIncentive; uint rewardPoolSharePerc; + address createdBy; } uint256 maxRewardPoolPercForMC; @@ -42,6 +43,7 @@ contract MarketRegistryNew is MarketRegistry { mapping(address => MarketCreationRewardUserData) private marketCreationRewardUserData; //Of user mapping(address => MarketCreationRewardData) private marketCreationRewardData; //Of user + event MarketCreatorRewardPoolShare(address indexed createdBy, address indexed marketAddress, uint256 plotIncentive, uint256 ethIncentive); event MarketCreationReward(address indexed createdBy, address marketAddress, uint256 plotIncentive, uint256 gasUsed, uint256 gasCost, uint256 gasPriceConsidered, uint256 gasPriceGiven, uint256 maxGasCap, uint256 rewardPoolSharePerc); event ClaimedMarketCreationReward(address indexed user, uint256 ethIncentive, uint256 plotIncentive); @@ -109,6 +111,7 @@ contract MarketRegistryNew is MarketRegistry { */ function _checkIfCreatorStaked(address _market) internal { uint256 tokensLocked = ITokenController(tokenController).tokensLockedAtTime(msg.sender, "SM", now); + marketCreationRewardData[_market].createdBy = msg.sender; //Intentionally performed mul operation after div, to get absolute value instead of decimals marketCreationRewardData[_market].rewardPoolSharePerc = Math.min( @@ -239,6 +242,7 @@ contract MarketRegistryNew is MarketRegistry { require(isMarket(msg.sender)); marketCreationRewardData[msg.sender].plotIncentive = marketCreatorIncentive[0]; marketCreationRewardData[msg.sender].ethIncentive = marketCreatorIncentive[1]; + emit MarketCreatorRewardPoolShare(msg.sender, marketCreationRewardData[msg.sender].createdBy, marketCreatorIncentive[0], marketCreatorIncentive[1]); emit MarketResult(msg.sender, _totalReward, winningOption, closeValue, _roundId); } From f8fbe7a469ce9f27a26c06ec2ad2a173bfa9bd24 Mon Sep 17 00:00:00 2001 From: udkreddySomish Date: Thu, 12 Nov 2020 10:50:34 +0530 Subject: [PATCH 50/58] Added user address argument to check pending market creation rewards --- contracts/MarketRegistryNew.sol | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/contracts/MarketRegistryNew.sol b/contracts/MarketRegistryNew.sol index bfda4449..9808e369 100644 --- a/contracts/MarketRegistryNew.sol +++ b/contracts/MarketRegistryNew.sol @@ -205,20 +205,21 @@ contract MarketRegistryNew is MarketRegistry { /** * @dev function to get pending reward of user for initiating market creation calls as per the new incetive calculations + * @param _user Address of user for whom pending rewards to be checked * @return plotIncentive Incentives given for creating market as per the gas consumed * @return pendingPLOTReward PLOT Reward pool share of markets created by user * @return pendingETHReward ETH Reward pool share of markets created by user */ - function getPendingMarketCreationRewards() external view returns(uint256 plotIncentive, uint256 pendingPLOTReward, uint256 pendingETHReward){ - plotIncentive = marketCreationRewardUserData[msg.sender].incentives; - (pendingETHReward, pendingPLOTReward) = _getPendingRewardPoolIncentives(); + function getPendingMarketCreationRewards(address _user) external view returns(uint256 plotIncentive, uint256 pendingPLOTReward, uint256 pendingETHReward){ + plotIncentive = marketCreationRewardUserData[_user].incentives; + (pendingETHReward, pendingPLOTReward) = _getPendingRewardPoolIncentives(_user); } /** * @dev internal function to calculate market reward pool share incentives for market creator */ - function _getPendingRewardPoolIncentives() internal view returns(uint256 ethIncentive, uint256 plotIncentive) { - MarketCreationRewardUserData memory rewardData = marketCreationRewardUserData[msg.sender]; + function _getPendingRewardPoolIncentives(address _user) internal view returns(uint256 ethIncentive, uint256 plotIncentive) { + MarketCreationRewardUserData memory rewardData = marketCreationRewardUserData[_user]; uint256 len = rewardData.marketsCreated.length; for(uint256 i = rewardData.lastClaimedIndex;i < len; i++) { MarketCreationRewardData memory marketData = marketCreationRewardData[rewardData.marketsCreated[i]]; From c21755da0f1193d418ef57160cf4f89a394d01ee Mon Sep 17 00:00:00 2001 From: udkreddySomish Date: Thu, 12 Nov 2020 10:54:29 +0530 Subject: [PATCH 51/58] Updated testcases --- test/24_UpgradedCreationIncentive.test.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/24_UpgradedCreationIncentive.test.js b/test/24_UpgradedCreationIncentive.test.js index 95b5793d..606a35c8 100644 --- a/test/24_UpgradedCreationIncentive.test.js +++ b/test/24_UpgradedCreationIncentive.test.js @@ -673,7 +673,7 @@ contract("MarketUtility", async function([user1, user2, user3, user4, user5, use let tx = await plotusNewInstance.createMarket(0,1, {gasPrice:450000, from:user10}); let openMarkets = await plotusNewInstance.getOpenMarkets(); let marketInstance = await MarketNew.at(openMarkets[0][1]); - let pendingRewards = await plotusNewInstance.getPendingMarketCreationRewards(); + let pendingRewards = await plotusNewInstance.getPendingMarketCreationRewards(user1); await increaseTime(100); await marketInstance.placePrediction(ethAddress, "100000000000000000", 3, 5, { value: "100000000000000000", @@ -692,7 +692,7 @@ contract("MarketUtility", async function([user1, user2, user3, user4, user5, use from: user7, }); await increaseTime(10000); - pendingRewards = await plotusNewInstance.getPendingMarketCreationRewards(); + pendingRewards = await plotusNewInstance.getPendingMarketCreationRewards(user1); await marketInstance.settleMarket(); let proposalId = await governance.getProposalLength(); await marketInstance.raiseDispute("9999999000000000","raise dispute","this is description","this is solution hash", { from: user10 }); @@ -735,7 +735,7 @@ contract("MarketUtility", async function([user1, user2, user3, user4, user5, use let oldBalance = parseFloat(await plotusToken.balanceOf(user10)); let oldBalanceEth = parseFloat(await web3.eth.getBalance(user10)); - pendingRewards = await plotusNewInstance.getPendingMarketCreationRewards({from:user10}); + pendingRewards = await plotusNewInstance.getPendingMarketCreationRewards(user10, {from:user10}); tx = await plotusNewInstance.claimCreationRewardV2(100, {from:user10}); let newBalance = parseFloat(await plotusToken.balanceOf(user10)); let newBalanceEth = parseFloat(await web3.eth.getBalance(user10)); From cf68f6b8717ded7fc720af9067ace5eb9cd97c02 Mon Sep 17 00:00:00 2001 From: udkreddySomish Date: Tue, 17 Nov 2020 09:25:21 +0530 Subject: [PATCH 52/58] Added a functionality to pause market creation of particular type through governance --- contracts/MarketRegistryNew.sol | 17 +++- test/24_UpgradedCreationIncentive.test.js | 112 +++++++++++++++++++--- 2 files changed, 115 insertions(+), 14 deletions(-) diff --git a/contracts/MarketRegistryNew.sol b/contracts/MarketRegistryNew.sol index 9808e369..e590ee89 100644 --- a/contracts/MarketRegistryNew.sol +++ b/contracts/MarketRegistryNew.sol @@ -41,8 +41,9 @@ contract MarketRegistryNew is MarketRegistry { uint256 plotStakeForRewardPoolShare; uint256 rewardPoolShareThreshold; - mapping(address => MarketCreationRewardUserData) private marketCreationRewardUserData; //Of user - mapping(address => MarketCreationRewardData) private marketCreationRewardData; //Of user + mapping(address => MarketCreationRewardUserData) internal marketCreationRewardUserData; //Of user + mapping(address => MarketCreationRewardData) internal marketCreationRewardData; //Of user + mapping(uint256 => bool) internal marketCreationPausedOfType; event MarketCreatorRewardPoolShare(address indexed createdBy, address indexed marketAddress, uint256 plotIncentive, uint256 ethIncentive); event MarketCreationReward(address indexed createdBy, address marketAddress, uint256 plotIncentive, uint256 gasUsed, uint256 gasCost, uint256 gasPriceConsidered, uint256 gasPriceGiven, uint256 maxGasCap, uint256 rewardPoolSharePerc); event ClaimedMarketCreationReward(address indexed user, uint256 ethIncentive, uint256 plotIncentive); @@ -67,6 +68,7 @@ contract MarketRegistryNew is MarketRegistry { * @param _marketCurrencyIndex the index of market currency. */ function createMarket(uint256 _marketType, uint256 _marketCurrencyIndex) public payable{ + require(!marketCreationPausedOfType[_marketType]); uint256 gasProvided = gasleft(); address penultimateMarket = marketCreationData[_marketType][_marketCurrencyIndex].penultimateMarket; if(penultimateMarket != address(0)) { @@ -120,6 +122,14 @@ contract MarketRegistryNew is MarketRegistry { ); } + /** + * @dev Pause Market creation of `_marketType` Type. + */ + function toggleMarketCreationType(uint256 _marketType, bool _flag) external onlyAuthorizedToGovern { + require(marketCreationPausedOfType[_marketType] != _flag); + marketCreationPausedOfType[_marketType] = _flag; + } + /** * @dev Get market reward pool share percent to be rewarded to market creator */ @@ -300,4 +310,7 @@ contract MarketRegistryNew is MarketRegistry { } } + function addInitialMarketTypesAndStart(uint64 _marketStartTime, address _ethMarketImplementation, address _btcMarketImplementation) external { + revert("Deprecated"); + } } diff --git a/test/24_UpgradedCreationIncentive.test.js b/test/24_UpgradedCreationIncentive.test.js index 606a35c8..bd9cd0cf 100644 --- a/test/24_UpgradedCreationIncentive.test.js +++ b/test/24_UpgradedCreationIncentive.test.js @@ -12,6 +12,7 @@ const MockWeth = artifacts.require("MockWeth"); const MarketUtility = artifacts.require("MarketUtility"); const MockConfig = artifacts.require("MockConfig"); const Governance = artifacts.require("Governance"); +const ProposalCategory = artifacts.require("ProposalCategory"); const MockUniswapRouter = artifacts.require("MockUniswapRouter"); const MockUniswapV2Pair = artifacts.require("MockUniswapV2Pair"); const MockUniswapFactory = artifacts.require('MockUniswapFactory'); @@ -43,7 +44,7 @@ contract("MarketUtility", async function([user1, user2, user3, user4, user5, use plotusNewInstance, governance, mockUniswapV2Pair, mockUniswapFactory, weth, - chainlinkGasAgg; + chainlinkGasAgg, pc; before(async () => { masterInstance = await OwnedUpgradeabilityProxy.deployed(); masterInstance = await Master.at(masterInstance.address); @@ -55,6 +56,8 @@ contract("MarketUtility", async function([user1, user2, user3, user4, user5, use memberRoles = await MemberRoles.at(memberRoles); governance = await masterInstance.getLatestAddress(web3.utils.toHex("GV")); governance = await Governance.at(governance); + pc = await masterInstance.getLatestAddress(web3.utils.toHex("PC")); + pc = await ProposalCategory.at(pc); MockUniswapRouterInstance = await MockUniswapRouter.deployed(); mockUniswapFactory = await MockUniswapFactory.deployed(); plotusNewInstance = await Plotus.at(plotusNewAddress); @@ -240,7 +243,7 @@ contract("MarketUtility", async function([user1, user2, user3, user4, user5, use it("If gas is provided more than 125% of fast gas, reward should be as per 125% fast gas", async function() { await increaseTime(3610); let tx = await plotusNewInstance.createMarket(0,1, {gasPrice:1000000}); - eventData = tx.logs[2].args; + eventData = tx.logs[tx.logs.length-1].args; let gasUsed = eventData.gasUsed.toNumber(); let gasPrice = 562500; estimatedGasCost = gasPrice*gasUsed; @@ -262,7 +265,7 @@ contract("MarketUtility", async function([user1, user2, user3, user4, user5, use await chainlinkGasAgg.setLatestAnswer(1250000); await increaseTime(3610); let tx = await plotusNewInstance.createMarket(0,1, {gasPrice:2000000}); - eventData = tx.logs[2].args; + eventData = tx.logs[tx.logs.length-1].args; let gasUsed = eventData.gasUsed.toNumber(); let maxGas = await plotusNewInstance.getUintParameters(toHex("MAXGAS")); let gasPrice = Math.min(maxGas[1].toNumber(), 1250000*1.25); @@ -302,7 +305,7 @@ contract("MarketUtility", async function([user1, user2, user3, user4, user5, use }); let rewardPoolEth = 0.1; let rewardPoolPlot = 99.95; - eventData = tx.logs[2].args; + eventData = tx.logs[tx.logs.length-1].args; let gasUsed = eventData.gasUsed.toNumber(); let maxGas = await plotusNewInstance.getUintParameters(toHex("MAXGAS")); let gasPrice = Math.min(maxGas[1].toNumber(), 450000*1.25); @@ -349,7 +352,7 @@ contract("MarketUtility", async function([user1, user2, user3, user4, user5, use }); let rewardPoolEth = 0.1; let rewardPoolPlot = 99.95; - eventData = tx.logs[2].args; + eventData = tx.logs[tx.logs.length-1].args; let gasUsed = eventData.gasUsed.toNumber(); let maxGas = await plotusNewInstance.getUintParameters(toHex("MAXGAS")); let gasPrice = Math.min(maxGas[1].toNumber(), 450000*1.25); @@ -394,7 +397,7 @@ contract("MarketUtility", async function([user1, user2, user3, user4, user5, use let rewardPoolEth = 0.1; let rewardPoolPlot = 9.95; try { - eventData = tx.logs[2].args; + eventData = tx.logs[tx.logs.length-1].args; } catch(e) { eventData = tx.logs[1].args; } @@ -430,7 +433,7 @@ contract("MarketUtility", async function([user1, user2, user3, user4, user5, use await increaseTime(3610); let tx = await plotusNewInstance.createMarket(0,1, {gasPrice:450000, from:user4}); try { - eventData = tx.logs[2].args; + eventData = tx.logs[tx.logs.length-1].args; } catch(e) { eventData = tx.logs[1].args; } @@ -495,7 +498,7 @@ contract("MarketUtility", async function([user1, user2, user3, user4, user5, use let rewardPoolEth = 0.1; let rewardPoolPlot = 99.95; try { - eventData = tx.logs[2].args; + eventData = tx.logs[tx.logs.length-1].args; } catch(e) { eventData = tx.logs[1].args; } @@ -543,7 +546,7 @@ contract("MarketUtility", async function([user1, user2, user3, user4, user5, use let rewardPoolEth = 0.1; let rewardPoolPlot = 99.95; try { - eventData = tx.logs[2].args; + eventData = tx.logs[tx.logs.length-1].args; } catch(e) { eventData = tx.logs[1].args; } @@ -581,7 +584,7 @@ contract("MarketUtility", async function([user1, user2, user3, user4, user5, use let rewardPoolEth = 0; let rewardPoolPlot = 0; try { - eventData = tx.logs[2].args; + eventData = tx.logs[tx.logs.length-1].args; } catch(e) { eventData = tx.logs[1].args; } @@ -634,7 +637,7 @@ contract("MarketUtility", async function([user1, user2, user3, user4, user5, use let rewardPoolEth = 0.1; let rewardPoolPlot = 99.95; try { - eventData = tx.logs[2].args; + eventData = tx.logs[tx.logs.length-1].args; } catch(e) { eventData = tx.logs[1].args; } @@ -718,7 +721,7 @@ contract("MarketUtility", async function([user1, user2, user3, user4, user5, use let rewardPoolEth = 0.99; let rewardPoolPlot = 99.95; try { - eventData = tx.logs[2].args; + eventData = tx.logs[tx.logs.length-1].args; } catch(e) { eventData = tx.logs[1].args; } @@ -745,6 +748,91 @@ contract("MarketUtility", async function([user1, user2, user3, user4, user5, use assert.equal((newBalanceEth/1e18).toFixed(2), (oldBalanceEth/1e18 + rewardPoolEth*rewardPoolSharePerc/10000).toFixed(2)); }); + it('Should Add category to pause market creation of particular type of market', async function() { + let c1 = await pc.totalCategories(); + //proposal to add category + let actionHash = encode1( + ["string", "uint256", "uint256", "uint256", "uint256[]", "uint256", "string", "address", "bytes2", "uint256[]", "string"], + [ + "Pause", + 1, + 50, + 50, + [1], + 86400, + "QmZQhJunZesYuCJkdGwejSATTR8eynUgV8372cHvnAPMaM", + nullAddress, + toHex("PL"), + [0, 0, 0, 1], + "toggleMarketCreationType(uint256,bool)", + ] + ); + let p1 = await governance.getProposalLength(); + await governance.createProposalwithSolution("Add new member", "Add new member", "Addnewmember", 3, "Add new member", actionHash); + await governance.submitVote(p1.toNumber(), 1); + await governance.closeProposal(p1.toNumber()); + let cat2 = await pc.totalCategories(); + assert.notEqual(c1.toNumber(), cat2.toNumber(), "category not updated"); + }); + + it('Should pause market creation of particular type of market', async function() { + await plotusNewInstance.createMarket(0,0); + await increaseTime(604800); + let c1 = await pc.totalCategories(); + //proposal to add category + actionHash = encode1( + ["uint256","bool"], + [ + 0, true + ] + ); + let p1 = await governance.getProposalLength(); + await governance.createProposalwithSolution("Add new member", "Add new member", "Addnewmember", c1 - 1, "Add new member", actionHash); + await governance.submitVote(p1.toNumber(), 1); + await governance.closeProposal(p1.toNumber()); + assert.equal((await governance.proposalActionStatus(p1.toNumber()))/1, 3) + let cat2 = await pc.totalCategories(); + assert.notEqual(c1, cat2, "category not updated"); + await assertRevert(plotusNewInstance.createMarket(0,0)); + }); + + it('Should not execute if market is already paused', async function() { + await increaseTime(604800); + let c1 = await pc.totalCategories(); + //proposal to add category + actionHash = encode1( + ["uint256","bool"], + [ + 0, true + ] + ); + let p1 = await governance.getProposalLength(); + await governance.createProposalwithSolution("Add new member", "Add new member", "Addnewmember", c1 - 1, "Add new member", actionHash); + await governance.submitVote(p1.toNumber(), 1); + await governance.closeProposal(p1.toNumber()); + assert.equal((await governance.proposalActionStatus(p1.toNumber()))/1, 1) + }); + + it('Should resume market creation of particular type of market', async function() { + await increaseTime(604800); + await assertRevert(plotusNewInstance.createMarket(0,0)); + await increaseTime(604800); + let c1 = await pc.totalCategories(); + //proposal to add category + actionHash = encode1( + ["uint256","bool"], + [ + 0, false + ] + ); + let p1 = await governance.getProposalLength(); + await governance.createProposalwithSolution("Add new member", "Add new member", "Addnewmember", c1 - 1, "Add new member", actionHash); + await governance.submitVote(p1.toNumber(), 1); + await governance.closeProposal(p1.toNumber()); + assert.equal((await governance.proposalActionStatus(p1.toNumber()))/1, 3) + await plotusNewInstance.createMarket(0,0); + }); + it('Should update MAXRPSP variable', async function() { await updateParameter(20, 2, 'MAXRPSP', plotusNewInstance, 'configUint', 5000); configData = await plotusNewInstance.getUintParameters(toHex('MAXRPSP')); From 81e471488ee906b413433151f3496205e91eb046 Mon Sep 17 00:00:00 2001 From: udkreddySomish Date: Tue, 17 Nov 2020 09:27:47 +0530 Subject: [PATCH 53/58] Updated comments --- contracts/MarketRegistryNew.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/MarketRegistryNew.sol b/contracts/MarketRegistryNew.sol index e590ee89..47b14c03 100644 --- a/contracts/MarketRegistryNew.sol +++ b/contracts/MarketRegistryNew.sol @@ -123,7 +123,7 @@ contract MarketRegistryNew is MarketRegistry { } /** - * @dev Pause Market creation of `_marketType` Type. + * @dev Toggle Market creation of `_marketType` Type. */ function toggleMarketCreationType(uint256 _marketType, bool _flag) external onlyAuthorizedToGovern { require(marketCreationPausedOfType[_marketType] != _flag); From 90ac621cf5f0838de1e60e975d331da3d775dce9 Mon Sep 17 00:00:00 2001 From: udkreddySomish Date: Wed, 18 Nov 2020 16:10:53 +0530 Subject: [PATCH 54/58] Corrected event data --- contracts/MarketRegistryNew.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/MarketRegistryNew.sol b/contracts/MarketRegistryNew.sol index 9808e369..b6c5feb7 100644 --- a/contracts/MarketRegistryNew.sol +++ b/contracts/MarketRegistryNew.sol @@ -243,7 +243,7 @@ contract MarketRegistryNew is MarketRegistry { require(isMarket(msg.sender)); marketCreationRewardData[msg.sender].plotIncentive = marketCreatorIncentive[0]; marketCreationRewardData[msg.sender].ethIncentive = marketCreatorIncentive[1]; - emit MarketCreatorRewardPoolShare(msg.sender, marketCreationRewardData[msg.sender].createdBy, marketCreatorIncentive[0], marketCreatorIncentive[1]); + emit MarketCreatorRewardPoolShare(marketCreationRewardData[msg.sender].createdBy, msg.sender, marketCreatorIncentive[0], marketCreatorIncentive[1]); emit MarketResult(msg.sender, _totalReward, winningOption, closeValue, _roundId); } From bfc56227066f65d29db995be157261cb1d9a19e0 Mon Sep 17 00:00:00 2001 From: udkreddySomish Date: Thu, 19 Nov 2020 13:56:13 +0530 Subject: [PATCH 55/58] Fixed bug in claim reward --- contracts/MarketRegistryNew.sol | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/contracts/MarketRegistryNew.sol b/contracts/MarketRegistryNew.sol index b6c5feb7..ff501be1 100644 --- a/contracts/MarketRegistryNew.sol +++ b/contracts/MarketRegistryNew.sol @@ -162,10 +162,10 @@ contract MarketRegistryNew is MarketRegistry { */ function claimCreationRewardV2(uint256 _maxRecords) external { uint256 pendingPLOTReward = marketCreationRewardUserData[msg.sender].incentives; - require(pendingPLOTReward > 0); delete marketCreationRewardUserData[msg.sender].incentives; (uint256 ethIncentive, uint256 plotIncentive) = _getRewardPoolIncentives(_maxRecords); pendingPLOTReward = pendingPLOTReward.add(plotIncentive); + require(pendingPLOTReward > 0 || ethIncentive > 0, "No pending"); _transferAsset(address(plotToken), msg.sender, pendingPLOTReward); _transferAsset(ETH_ADDRESS, msg.sender, ethIncentive); emit ClaimedMarketCreationReward(msg.sender, ethIncentive, pendingPLOTReward); @@ -182,18 +182,16 @@ contract MarketRegistryNew is MarketRegistry { uint256 i; for(i = rewardData.lastClaimedIndex;i < len && count < _maxRecords; i++) { MarketCreationRewardData storage marketData = marketCreationRewardData[rewardData.marketsCreated[i]]; - if(marketData.ethIncentive > 0 || marketData.plotIncentive > 0) { - ( , , , , , , , , uint _predictionStatus) = IMarket(rewardData.marketsCreated[i]).getData(); - if(_predictionStatus == uint(IMarket.PredictionStatus.Settled)) { - ethIncentive = ethIncentive.add(marketData.ethIncentive); - plotIncentive = plotIncentive.add(marketData.plotIncentive); - delete marketData.ethIncentive; - delete marketData.plotIncentive; - count++; - } else { - if(lastClaimed == len) { - lastClaimed = i; - } + ( , , , , , , , , uint _predictionStatus) = IMarket(rewardData.marketsCreated[i]).getData(); + if(_predictionStatus == uint(IMarket.PredictionStatus.Settled)) { + ethIncentive = ethIncentive.add(marketData.ethIncentive); + plotIncentive = plotIncentive.add(marketData.plotIncentive); + delete marketData.ethIncentive; + delete marketData.plotIncentive; + count++; + } else { + if(lastClaimed == len) { + lastClaimed = i; } } } From 78c8be654d1cc534cc853c1ad0df525716fdc212 Mon Sep 17 00:00:00 2001 From: udkreddySomish Date: Thu, 19 Nov 2020 13:56:45 +0530 Subject: [PATCH 56/58] Updated testcases --- test/24_UpgradedCreationIncentive.test.js | 321 +++++++++++++++++++++- 1 file changed, 309 insertions(+), 12 deletions(-) diff --git a/test/24_UpgradedCreationIncentive.test.js b/test/24_UpgradedCreationIncentive.test.js index 606a35c8..2e9da6e9 100644 --- a/test/24_UpgradedCreationIncentive.test.js +++ b/test/24_UpgradedCreationIncentive.test.js @@ -32,7 +32,7 @@ var incentivesGained = 0; const ethAddress = "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE"; var nullAddress = "0x0000000000000000000000000000"; -contract("MarketUtility", async function([user1, user2, user3, user4, user5, user6, user7, user8, user9, user10, user11, user12, user13]) { +contract("MarketUtility", async function([user1, user2, user3, user4, user5, user6, user7, user8, user9, user10, user11, user12, user13, user14]) { let masterInstance, plotusToken, marketConfig, @@ -240,7 +240,7 @@ contract("MarketUtility", async function([user1, user2, user3, user4, user5, use it("If gas is provided more than 125% of fast gas, reward should be as per 125% fast gas", async function() { await increaseTime(3610); let tx = await plotusNewInstance.createMarket(0,1, {gasPrice:1000000}); - eventData = tx.logs[2].args; + eventData = tx.logs[tx.logs.length-1].args; let gasUsed = eventData.gasUsed.toNumber(); let gasPrice = 562500; estimatedGasCost = gasPrice*gasUsed; @@ -262,7 +262,7 @@ contract("MarketUtility", async function([user1, user2, user3, user4, user5, use await chainlinkGasAgg.setLatestAnswer(1250000); await increaseTime(3610); let tx = await plotusNewInstance.createMarket(0,1, {gasPrice:2000000}); - eventData = tx.logs[2].args; + eventData = tx.logs[tx.logs.length-1].args; let gasUsed = eventData.gasUsed.toNumber(); let maxGas = await plotusNewInstance.getUintParameters(toHex("MAXGAS")); let gasPrice = Math.min(maxGas[1].toNumber(), 1250000*1.25); @@ -302,7 +302,7 @@ contract("MarketUtility", async function([user1, user2, user3, user4, user5, use }); let rewardPoolEth = 0.1; let rewardPoolPlot = 99.95; - eventData = tx.logs[2].args; + eventData = tx.logs[tx.logs.length-1].args; let gasUsed = eventData.gasUsed.toNumber(); let maxGas = await plotusNewInstance.getUintParameters(toHex("MAXGAS")); let gasPrice = Math.min(maxGas[1].toNumber(), 450000*1.25); @@ -349,7 +349,7 @@ contract("MarketUtility", async function([user1, user2, user3, user4, user5, use }); let rewardPoolEth = 0.1; let rewardPoolPlot = 99.95; - eventData = tx.logs[2].args; + eventData = tx.logs[tx.logs.length-1].args; let gasUsed = eventData.gasUsed.toNumber(); let maxGas = await plotusNewInstance.getUintParameters(toHex("MAXGAS")); let gasPrice = Math.min(maxGas[1].toNumber(), 450000*1.25); @@ -394,7 +394,7 @@ contract("MarketUtility", async function([user1, user2, user3, user4, user5, use let rewardPoolEth = 0.1; let rewardPoolPlot = 9.95; try { - eventData = tx.logs[2].args; + eventData = tx.logs[tx.logs.length-1].args; } catch(e) { eventData = tx.logs[1].args; } @@ -430,7 +430,7 @@ contract("MarketUtility", async function([user1, user2, user3, user4, user5, use await increaseTime(3610); let tx = await plotusNewInstance.createMarket(0,1, {gasPrice:450000, from:user4}); try { - eventData = tx.logs[2].args; + eventData = tx.logs[tx.logs.length-1].args; } catch(e) { eventData = tx.logs[1].args; } @@ -495,7 +495,7 @@ contract("MarketUtility", async function([user1, user2, user3, user4, user5, use let rewardPoolEth = 0.1; let rewardPoolPlot = 99.95; try { - eventData = tx.logs[2].args; + eventData = tx.logs[tx.logs.length-1].args; } catch(e) { eventData = tx.logs[1].args; } @@ -543,7 +543,7 @@ contract("MarketUtility", async function([user1, user2, user3, user4, user5, use let rewardPoolEth = 0.1; let rewardPoolPlot = 99.95; try { - eventData = tx.logs[2].args; + eventData = tx.logs[tx.logs.length-1].args; } catch(e) { eventData = tx.logs[1].args; } @@ -581,7 +581,7 @@ contract("MarketUtility", async function([user1, user2, user3, user4, user5, use let rewardPoolEth = 0; let rewardPoolPlot = 0; try { - eventData = tx.logs[2].args; + eventData = tx.logs[tx.logs.length-1].args; } catch(e) { eventData = tx.logs[1].args; } @@ -607,6 +607,54 @@ contract("MarketUtility", async function([user1, user2, user3, user4, user5, use assert.equal((newBalanceEth/1e18).toFixed(2), (oldBalanceEth/1e18 + rewardPoolEth*rewardPoolSharePerc/10000).toFixed(2)); }); + it("Scenario 8: Should not be able to get reward pool share of market more than max cap of 5%", async function() { + await plotusToken.transfer(user14, toWei(500000)); + await plotusToken.approve(tokenController.address, "1000000000000000000000000", { from: user14 }); + await tokenController.lock("0x534d", toWei(500000), 86400 * 30, { from: user14 }); + await chainlinkGasAgg.setLatestAnswer(450000); + await increaseTime(3610); + let tx = await plotusNewInstance.createMarket(0,1, {gasPrice:450000, from:user14}); + let openMarkets = await plotusNewInstance.getOpenMarkets(); + let marketInstance = await MarketNew.at(openMarkets[0][1]); + await increaseTime(100); + await marketInstance.placePrediction(ethAddress, "100000000000000000", 3, 5, { + value: "100000000000000000", + from: user7, + }); + await plotusToken.transfer(user7, toWei(10000)); + await plotusToken.approve(tokenController.address, toWei(1000000000000000000), {from: user7}); + await marketInstance.placePrediction(plotusToken.address, "100000000000000000000", 3, 5, { + from: user7, + }); + let rewardPoolEth = 0.1; + let rewardPoolPlot = 99.95; + try { + eventData = tx.logs[tx.logs.length-1].args; + } catch(e) { + eventData = tx.logs[1].args; + } + let gasUsed = eventData.gasUsed.toNumber(); + let maxGas = await plotusNewInstance.getUintParameters(toHex("MAXGAS")); + let gasPrice = Math.min(maxGas[1].toNumber(), 450000*1.25); + estimatedGasCost = gasPrice*gasUsed; + let costInETH = estimatedGasCost; + let worthInPLOT = await marketConfig.getValueAndMultiplierParameters(ethAddress, costInETH + ""); + incentivesGained = eventData.plotIncentive/1; + let rewardPoolSharePerc = eventData.rewardPoolSharePerc; + assert.equal(rewardPoolSharePerc/1, 500) + assert.equal(eventData.plotIncentive/1, worthInPLOT[1]/1); + await increaseTime(10000); + await marketInstance.settleMarket(); + await increaseTime(10000); + let oldBalance = parseFloat(await plotusToken.balanceOf(user14)); + let oldBalanceEth = parseFloat(await web3.eth.getBalance(user14)); + tx = await plotusNewInstance.claimCreationRewardV2(100, {from:user14}); + let newBalance = parseFloat(await plotusToken.balanceOf(user14)); + let newBalanceEth = parseFloat(await web3.eth.getBalance(user14)); + assert.equal((newBalance/1e18).toFixed(2), (oldBalance/1e18 + incentivesGained/1e18 + rewardPoolPlot*rewardPoolSharePerc/10000).toFixed(2)); + assert.equal((newBalanceEth/1e18).toFixed(2), (oldBalanceEth/1e18 + rewardPoolEth*rewardPoolSharePerc/10000).toFixed(2)); + }); + it("Raise Dispute and reject: Scenario 2: Should be able to get more reward pool share of market if market creator had staked tokens", async function() { await plotusToken.transfer(user10, toWei(250000)); await plotusToken.approve(tokenController.address, "1000000000000000000000000", { from: user10 }); @@ -634,7 +682,7 @@ contract("MarketUtility", async function([user1, user2, user3, user4, user5, use let rewardPoolEth = 0.1; let rewardPoolPlot = 99.95; try { - eventData = tx.logs[2].args; + eventData = tx.logs[tx.logs.length-1].args; } catch(e) { eventData = tx.logs[1].args; } @@ -718,7 +766,7 @@ contract("MarketUtility", async function([user1, user2, user3, user4, user5, use let rewardPoolEth = 0.99; let rewardPoolPlot = 99.95; try { - eventData = tx.logs[2].args; + eventData = tx.logs[tx.logs.length-1].args; } catch(e) { eventData = tx.logs[1].args; } @@ -745,6 +793,255 @@ contract("MarketUtility", async function([user1, user2, user3, user4, user5, use assert.equal((newBalanceEth/1e18).toFixed(2), (oldBalanceEth/1e18 + rewardPoolEth*rewardPoolSharePerc/10000).toFixed(2)); }); + let plotGasIncentiveForMarket1, + plotPoolShareExpectedForMarket1, + ethExpectedForMarket1, + plotGasIncentiveForMarket2, + plotPoolShareExpectedForMarket2, + ethExpectedForMarket2, + plotGasIncentiveForMarket3, + plotPoolShareExpectedForMarket3, + ethExpectedForMarket3, + plotGasIncentiveForMarket4, + plotPoolShareExpectedForMarket4, + ethExpectedForMarket4, market1, market2, market3, market4; + it("Create Market 1", async function() { + await chainlinkGasAgg.setLatestAnswer(450000); + await increaseTime(604800); + let tx = await plotusNewInstance.createMarket(0,0, {gasPrice:450000, from:user2}); + await plotusNewInstance.claimCreationRewardV2(5, {from: user2}); + let openMarkets = await plotusNewInstance.getOpenMarkets(); + let marketInstance = await MarketNew.at(openMarkets[0][0]); + await increaseTime(100); + await marketInstance.placePrediction(ethAddress, "100000000000000000", 3, 5, { + value: "100000000000000000", + from: user7, + }); + await marketInstance.placePrediction(ethAddress, "1000000000000000000", 1, 5, { + value: "1000000000000000000", + from: user7, + }); + await plotusToken.transfer(user7, toWei(10000)); + await plotusToken.approve(tokenController.address, toWei(1000000000000000000), {from: user7}); + await marketInstance.placePrediction(plotusToken.address, "100000000000000000000", 3, 5, { + from: user7, + }); + let rewardPoolEth = 0.1; + let rewardPoolPlot = 99.95; + eventData = tx.logs[tx.logs.length-1].args; + let gasUsed = eventData.gasUsed.toNumber(); + let maxGas = await plotusNewInstance.getUintParameters(toHex("MAXGAS")); + let gasPrice = Math.min(maxGas[1].toNumber(), 450000*1.25); + estimatedGasCost = gasPrice*gasUsed; + let costInETH = estimatedGasCost; + let worthInPLOT = await marketConfig.getValueAndMultiplierParameters(ethAddress, costInETH + ""); + incentivesGained = eventData.plotIncentive/1; + let rewardPoolSharePerc = eventData.rewardPoolSharePerc; + assert.equal(rewardPoolSharePerc/1, 50) + assert.equal(eventData.plotIncentive/1, worthInPLOT[1]/1); + plotGasIncentiveForMarket1 = incentivesGained/1e18 + plotPoolShareExpectedForMarket1 = rewardPoolPlot*rewardPoolSharePerc/10000; + ethExpectedForMarket1 = rewardPoolEth*rewardPoolSharePerc/10000; + }); + it("Create Market 2", async function() { + await chainlinkGasAgg.setLatestAnswer(450000); + let tx = await plotusNewInstance.createMarket(0,1, {gasPrice:450000, from:user2}); + await plotusNewInstance.claimCreationRewardV2(5, {from: user2}); + let openMarkets = await plotusNewInstance.getOpenMarkets(); + let marketInstance = await MarketNew.at(openMarkets[0][1]); + await increaseTime(100); + await marketInstance.placePrediction(ethAddress, "100000000000000000", 3, 5, { + value: "100000000000000000", + from: user12, + }); + await marketInstance.placePrediction(ethAddress, "1000000000000000000", 1, 5, { + value: "1000000000000000000", + from: user12, + }); + await plotusToken.transfer(user7, toWei(10000)); + await plotusToken.approve(tokenController.address, toWei(1000000000000000000), {from: user7}); + await marketInstance.placePrediction(plotusToken.address, "100000000000000000000", 3, 5, { + from: user7, + }); + await marketInstance.placePrediction(plotusToken.address, "100000000000000000000", 1, 5, { + from: user7, + }); + let rewardPoolEth = 0.99; + let rewardPoolPlot = 99.95; + eventData = tx.logs[tx.logs.length-1].args; + let gasUsed = eventData.gasUsed.toNumber(); + let maxGas = await plotusNewInstance.getUintParameters(toHex("MAXGAS")); + let gasPrice = Math.min(maxGas[1].toNumber(), 450000*1.25); + estimatedGasCost = gasPrice*gasUsed; + let costInETH = estimatedGasCost; + let worthInPLOT = await marketConfig.getValueAndMultiplierParameters(ethAddress, costInETH + ""); + incentivesGained = eventData.plotIncentive/1; + let rewardPoolSharePerc = eventData.rewardPoolSharePerc; + assert.equal(rewardPoolSharePerc/1, 50) + assert.equal(eventData.plotIncentive/1, worthInPLOT[1]/1); + plotGasIncentiveForMarket2 = incentivesGained/1e18 + plotPoolShareExpectedForMarket2 = rewardPoolPlot*rewardPoolSharePerc/10000; + ethExpectedForMarket2 = rewardPoolEth*rewardPoolSharePerc/10000; + }); + it("Create Market 3", async function() { + await chainlinkGasAgg.setLatestAnswer(450000); + let tx = await plotusNewInstance.createMarket(1,0, {gasPrice:450000, from:user2}); + await plotusNewInstance.claimCreationRewardV2(5, {from: user2}); + let openMarkets = await plotusNewInstance.getOpenMarkets(); + let marketInstance = await MarketNew.at(openMarkets[0][2]); + await increaseTime(100); + await marketInstance.placePrediction(ethAddress, "100000000000000000", 3, 5, { + value: "100000000000000000", + from: user7, + }); + await marketInstance.placePrediction(ethAddress, "1000000000000000000", 1, 5, { + value: "1000000000000000000", + from: user7, + }); + await plotusToken.transfer(user7, toWei(10000)); + await plotusToken.approve(tokenController.address, toWei(1000000000000000000), {from: user7}); + await marketInstance.placePrediction(plotusToken.address, "100000000000000000000", 3, 5, { + from: user7, + }); + let rewardPoolEth = 0.1; + let rewardPoolPlot = 99.95; + eventData = tx.logs[tx.logs.length-1].args; + let gasUsed = eventData.gasUsed.toNumber(); + let maxGas = await plotusNewInstance.getUintParameters(toHex("MAXGAS")); + let gasPrice = Math.min(maxGas[1].toNumber(), 450000*1.25); + estimatedGasCost = gasPrice*gasUsed; + let costInETH = estimatedGasCost; + let worthInPLOT = await marketConfig.getValueAndMultiplierParameters(ethAddress, costInETH + ""); + incentivesGained = eventData.plotIncentive/1; + let rewardPoolSharePerc = eventData.rewardPoolSharePerc; + assert.equal(rewardPoolSharePerc/1, 50) + assert.equal(eventData.plotIncentive/1, worthInPLOT[1]/1); + plotGasIncentiveForMarket3 = incentivesGained/1e18 + plotPoolShareExpectedForMarket3 = rewardPoolPlot*rewardPoolSharePerc/10000; + ethExpectedForMarket3 = rewardPoolEth*rewardPoolSharePerc/10000; + }); + it("Should not be able to claim market 1,2,3 pool share", async function(){ + tx = await assertRevert(plotusNewInstance.claimCreationRewardV2(100, {from:user2})); + await increaseTime(7200); + let openMarkets = await plotusNewInstance.getOpenMarkets(); + market1 = await MarketNew.at(openMarkets[0][0]); + market2 = await MarketNew.at(openMarkets[0][1]); + await market1.settleMarket(); + await market2.settleMarket(); + let proposalId = await governance.getProposalLength(); + await market2.raiseDispute(1400000000000,"raise dispute","this is description","this is solution hash", { from: user10 }); + }); + it("Should be able to claim market 1 rewards", async function() { + await increaseTime(7200); + let oldBalance = parseFloat(await plotusToken.balanceOf(user2)); + let oldBalanceEth = parseFloat(await web3.eth.getBalance(user2)); + tx = await plotusNewInstance.claimCreationRewardV2(100, {from:user2}); + let newBalance = parseFloat(await plotusToken.balanceOf(user2)); + let newBalanceEth = parseFloat(await web3.eth.getBalance(user2)); + assert.equal((newBalance/1e18).toFixed(2), (oldBalance/1e18 + plotPoolShareExpectedForMarket1).toFixed(2)); + assert.equal((newBalanceEth/1e18).toFixed(2), (oldBalanceEth/1e18 + ethExpectedForMarket1).toFixed(2)); + tx = await assertRevert(plotusNewInstance.claimCreationRewardV2(100, {from:user2})); + }); + it("Create Market 4", async function() { + await chainlinkGasAgg.setLatestAnswer(450000); + await increaseTime(3600); + let tx = await plotusNewInstance.createMarket(0,0, {gasPrice:450000, from:user2}); + await plotusNewInstance.claimCreationRewardV2(5, {from: user2}); + let openMarkets = await plotusNewInstance.getOpenMarkets(); + let marketInstance = await MarketNew.at(openMarkets[0][0]); + await increaseTime(100); + await marketInstance.placePrediction(ethAddress, "100000000000000000", 3, 5, { + value: "100000000000000000", + from: user7, + }); + await marketInstance.placePrediction(ethAddress, "1000000000000000000", 1, 5, { + value: "1000000000000000000", + from: user7, + }); + await plotusToken.transfer(user7, toWei(10000)); + await plotusToken.approve(tokenController.address, toWei(1000000000000000000), {from: user7}); + await marketInstance.placePrediction(plotusToken.address, "100000000000000000000", 3, 5, { + from: user7, + }); + let rewardPoolEth = 0.1; + let rewardPoolPlot = 99.95; + eventData = tx.logs[tx.logs.length-1].args; + let gasUsed = eventData.gasUsed.toNumber(); + let maxGas = await plotusNewInstance.getUintParameters(toHex("MAXGAS")); + let gasPrice = Math.min(maxGas[1].toNumber(), 450000*1.25); + estimatedGasCost = gasPrice*gasUsed; + let costInETH = estimatedGasCost; + let worthInPLOT = await marketConfig.getValueAndMultiplierParameters(ethAddress, costInETH + ""); + incentivesGained = eventData.plotIncentive/1; + let rewardPoolSharePerc = eventData.rewardPoolSharePerc; + assert.equal(rewardPoolSharePerc/1, 50) + assert.equal(eventData.plotIncentive/1, worthInPLOT[1]/1); + plotGasIncentiveForMarket4 = incentivesGained/1e18 + plotPoolShareExpectedForMarket4 = rewardPoolPlot*rewardPoolSharePerc/10000; + ethExpectedForMarket4 = rewardPoolEth*rewardPoolSharePerc/10000; + }); + it("Should be able to claim market 4 rewards", async function() { + await increaseTime(7200); + let openMarkets = await plotusNewInstance.getOpenMarkets(); + market1 = await MarketNew.at(openMarkets[0][0]); + await market1.settleMarket(); + await increaseTime(3600); + let oldBalance = parseFloat(await plotusToken.balanceOf(user2)); + let oldBalanceEth = parseFloat(await web3.eth.getBalance(user2)); + tx = await plotusNewInstance.claimCreationRewardV2(100, {from:user2}); + let newBalance = parseFloat(await plotusToken.balanceOf(user2)); + let newBalanceEth = parseFloat(await web3.eth.getBalance(user2)); + assert.equal((newBalance/1e18).toFixed(2), (oldBalance/1e18 + plotPoolShareExpectedForMarket4).toFixed(2)); + assert.equal((newBalanceEth/1e18).toFixed(2), (oldBalanceEth/1e18 + ethExpectedForMarket4).toFixed(2)); + tx = await assertRevert(plotusNewInstance.claimCreationRewardV2(100, {from:user2})); + }); + it("Accept dispute of Market2 and should be able to claim its reward pool share perc", async function() { + let proposalId = await governance.getProposalLength(); + proposalId = proposalId*1 - 1; + await plotusToken.approve(tokenController.address, "100000000000000000000000",{from : user2}); + await plotusToken.transfer(user2, toWei(30000)); + await tokenController.extendLock("0x4452",(86400*20),{from : user2}); + + await plotusToken.approve(tokenController.address, "100000000000000000000000",{from : user3}); + await plotusToken.transfer(user3, toWei(30000)); + await tokenController.extendLock("0x4452",(86400*20),{from : user3}); + + await plotusToken.approve(tokenController.address, "100000000000000000000000",{from : user4}); + await plotusToken.transfer(user4, toWei(30000)); + await tokenController.extendLock("0x4452",(86400*20),{from : user4}); + + await governance.submitVote(proposalId, 1, {from:user2}); + await governance.submitVote(proposalId, 1, {from:user3}); + await governance.submitVote(proposalId, 1, {from:user4}); + await increaseTime(604800); + await governance.closeProposal(proposalId); + await increaseTime(10000); + + let oldBalance = parseFloat(await plotusToken.balanceOf(user2)); + let oldBalanceEth = parseFloat(await web3.eth.getBalance(user2)); + tx = await plotusNewInstance.claimCreationRewardV2(100, {from:user2}); + let newBalance = parseFloat(await plotusToken.balanceOf(user2)); + let newBalanceEth = parseFloat(await web3.eth.getBalance(user2)); + assert.equal((newBalance/1e18).toFixed(2), (oldBalance/1e18 + plotPoolShareExpectedForMarket2).toFixed(2)); + assert.equal((newBalanceEth/1e18).toFixed(2), (oldBalanceEth/1e18 + ethExpectedForMarket2).toFixed(2)); + }); + + it("Should be able to claim market 3 rewards", async function() { + await increaseTime(604800); + let openMarkets = await plotusNewInstance.getOpenMarkets(); + market1 = await MarketNew.at(openMarkets[0][2]); + await market1.settleMarket(); + await increaseTime(604800); + let oldBalance = parseFloat(await plotusToken.balanceOf(user2)); + let oldBalanceEth = parseFloat(await web3.eth.getBalance(user2)); + tx = await plotusNewInstance.claimCreationRewardV2(100, {from:user2}); + let newBalance = parseFloat(await plotusToken.balanceOf(user2)); + let newBalanceEth = parseFloat(await web3.eth.getBalance(user2)); + assert.equal((newBalance/1e18).toFixed(2), (oldBalance/1e18 + plotPoolShareExpectedForMarket3).toFixed(2)); + assert.equal((newBalanceEth/1e18).toFixed(2), (oldBalanceEth/1e18 + ethExpectedForMarket3).toFixed(2)); + tx = await assertRevert(plotusNewInstance.claimCreationRewardV2(100, {from:user2})); + }); + it('Should update MAXRPSP variable', async function() { await updateParameter(20, 2, 'MAXRPSP', plotusNewInstance, 'configUint', 5000); configData = await plotusNewInstance.getUintParameters(toHex('MAXRPSP')); From e71c3cfcb81fcb573d851140d84c11b90e39bf94 Mon Sep 17 00:00:00 2001 From: udkreddySomish Date: Thu, 19 Nov 2020 19:00:38 +0530 Subject: [PATCH 57/58] Updated test cases --- test/24_UpgradedCreationIncentive.test.js | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/test/24_UpgradedCreationIncentive.test.js b/test/24_UpgradedCreationIncentive.test.js index 05102600..6203b8b4 100644 --- a/test/24_UpgradedCreationIncentive.test.js +++ b/test/24_UpgradedCreationIncentive.test.js @@ -853,9 +853,10 @@ contract("MarketUtility", async function([user1, user2, user3, user4, user5, use let openMarkets = await plotusNewInstance.getOpenMarkets(); let marketInstance = await MarketNew.at(openMarkets[0][1]); await increaseTime(100); + await plotusToken.transfer(user12, toWei(10000)); await marketInstance.placePrediction(ethAddress, "100000000000000000", 3, 5, { value: "100000000000000000", - from: user12, + from: user7, }); await marketInstance.placePrediction(ethAddress, "1000000000000000000", 1, 5, { value: "1000000000000000000", @@ -867,7 +868,7 @@ contract("MarketUtility", async function([user1, user2, user3, user4, user5, use from: user7, }); await marketInstance.placePrediction(plotusToken.address, "100000000000000000000", 1, 5, { - from: user7, + from: user12, }); let rewardPoolEth = 0.99; let rewardPoolPlot = 99.95; @@ -1029,6 +1030,14 @@ contract("MarketUtility", async function([user1, user2, user3, user4, user5, use assert.equal((newBalanceEth/1e18).toFixed(2), (oldBalanceEth/1e18 + ethExpectedForMarket2).toFixed(2)); }); + it("should be able to claim market participation rewards", async function() { + let reward = await market2.getReturn(user7); + await market2.claimReturn(user7 ,{from: user7}); + let balance = await plotusToken.balanceOf(market2.address); + let perc = await plotusNewInstance.getMarketCreatorRPoolShareParams(market2.address); + assert.equal(reward[0][0]/1e18, 99.95 + 99.95 - perc[0]*1*99.95/10000); + }) + it("Should be able to claim market 3 rewards", async function() { await increaseTime(604800); let openMarkets = await plotusNewInstance.getOpenMarkets(); From 4edc39b7712c3a1b0b1afd33b3c142d987aa9471 Mon Sep 17 00:00:00 2001 From: udkreddySomish Date: Thu, 19 Nov 2020 19:00:53 +0530 Subject: [PATCH 58/58] Fixed dependencies --- package.json | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/package.json b/package.json index c7c33a88..70edc755 100644 --- a/package.json +++ b/package.json @@ -16,17 +16,17 @@ "author": "", "license": "ISC", "dependencies": { - "@openzeppelin/contracts": "^2.5.0", - "@openzeppelin/test-helpers": "^0.5.6", - "bignumber.js": "^9.0.0", - "coveralls": "^3.0.2", - "ethereumjs-abi": "^0.6.8", - "ganache-cli": "^6.9.0", - "pify": "^5.0.0", - "solhint": "^3.2.0", - "solidity-coverage": "^0.7.1", - "truffle": "^5.1.18", - "web3": "^0.20.4" + "@openzeppelin/contracts": "2.5.0", + "@openzeppelin/test-helpers": "0.5.6", + "bignumber.js": "9.0.0", + "coveralls": "3.0.2", + "ethereumjs-abi": "0.6.8", + "ganache-cli": "6.9.0", + "pify": "5.0.0", + "solhint": "3.2.0", + "solidity-coverage": "0.7.1", + "truffle": "5.1.18", + "web3": "0.20.4" }, "devDependencies": { "chai": "^4.2.0"