diff --git a/README.md b/README.md index 763824edc..1bbd7ab63 100644 --- a/README.md +++ b/README.md @@ -29,23 +29,6 @@ Now, It's time to install the dependencies. Enter the smart-contracts directory ``` npm install ``` -Make sure you delete folder `bitcore-lib` from node_modules inside modules `eth-lightwallet` and `bitcore-mnemonic` - -We need to compile the contracts before deploying. -``` -npm run compile -``` -Now, You should start a private network on port 8545 using Ganache or something similar. To run the private network -
-On Windows, Execute file startGanache.bat present in smart-contracts/scripts directory
-On Linux or Mac OS Systems, run the startGanache.sh file while in smart-contracts/scripts directory -``` -./startGanache.sh -``` - -Then, you can deploy Plotx contracts using the migrate script. -``` -npm run deploy -``` If you want, you can run the test cases using ``` npm run test @@ -59,6 +42,8 @@ npm run coverage - PLOT Token: 0x72F020f8f3E8fd9382705723Cd26380f8D0c66Bb - Master: 0x03c41c5Aff6D541EF7D4c51c8B2E32a5d4427275 - MarketRegistry: 0xE210330d6768030e816d223836335079C7A0c851 +- AllMarkets: 0xb9448E3a0d95cFF578F9508084A0ed92D724c29A +- MarketCreationRewards: 0x22376814188De44e8B6f482daa98B050ac190B46 - MarketUtility: 0x2330058D49fA61D5C5405fA8B17fcD823c59F7Bb - Governance: 0x16763F192d529B420F33B699dC72F39f16620717 - ProposalCategory: 0x2D90743ef134b35cE415855F1c38ca47d65b314C diff --git a/contracts/Airdrop.sol b/contracts/Airdrop.sol index 737e4f270..cbcb37c73 100644 --- a/contracts/Airdrop.sol +++ b/contracts/Airdrop.sol @@ -1,6 +1,6 @@ pragma solidity 0.5.7; -import "./PlotXToken.sol"; +import "./interfaces/IToken.sol"; import "./external/openzeppelin-solidity/math/SafeMath.sol"; import "./external/openzeppelin-solidity/token/ERC20/ERC20.sol"; @@ -12,7 +12,7 @@ contract Airdrop { using SafeMath for uint256; IbLOTToken bLotToken; - PlotXToken public plotToken; + IToken public plotToken; address public owner; uint public endDate; uint public remainingbudget; @@ -43,7 +43,7 @@ contract Airdrop { require(_plotToken != address(0),"Can not be null address"); require(_bLotToken != address(0),"Can not be null address"); require(_endDate > now,"End date can not be past time"); - plotToken = PlotXToken(_plotToken); + plotToken = IToken(_plotToken); bLotToken = IbLOTToken(_bLotToken); owner = msg.sender; endDate = _endDate; diff --git a/contracts/AllMarkets.sol b/contracts/AllMarkets.sol new file mode 100644 index 000000000..b6e499f11 --- /dev/null +++ b/contracts/AllMarkets.sol @@ -0,0 +1,1133 @@ +/* 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 "./external/govblocks-protocol/interfaces/IGovernance.sol"; +import "./external/NativeMetaTransaction.sol"; +import "./interfaces/IMarketUtility.sol"; +import "./interfaces/IToken.sol"; +import "./interfaces/ITokenController.sol"; +import "./interfaces/IMarketCreationRewards.sol"; + +contract IMaster { + mapping(address => bool) public whitelistedSponsor; + function dAppToken() public view returns(address); + function getLatestAddress(bytes2 _module) public view returns(address); +} + + +contract Governed { + + address public masterAddress; // Name of the dApp, needs to be set by contracts inheriting this contract + IGovernance internal governance; + + /// @dev modifier that allows only the authorized addresses to execute the function + modifier onlyAuthorizedToGovern() { + require((address(governance)) == msg.sender); + _; + } + +} + +contract AllMarkets is Governed, NativeMetaTransaction { + using SafeMath32 for uint32; + using SafeMath64 for uint64; + using SafeMath128 for uint128; + using SafeMath for uint; + + enum PredictionStatus { + Live, + InSettlement, + Cooling, + InDispute, + Settled + } + + event Deposited(address indexed user, uint256 amount, uint256 timeStamp); + event Withdrawn(address indexed user, uint256 amount, uint256 timeStamp); + event MarketTypes(uint256 indexed index, uint32 predictionTime, uint32 cooldownTime, uint32 optionRangePerc, bool status, uint32 minTimePassed); + event MarketCurrencies(uint256 indexed index, address feedAddress, bytes32 currencyName, bool status); + event MarketQuestion(uint256 indexed marketIndex, bytes32 currencyName, uint256 indexed predictionType, uint256 startTime, uint256 predictionTime, uint256 neutralMinValue, uint256 neutralMaxValue); + event OptionPricingParams(uint256 indexed marketIndex, uint256 _stakingFactorMinStake,uint32 _stakingFactorWeightage,uint256 _currentPriceWeightage,uint32 _minTimePassed); + event MarketResult(uint256 indexed marketIndex, uint256 totalReward, uint256 winningOption, uint256 closeValue, uint256 roundId, uint256 daoFee, uint256 marketCreatorFee); + event ReturnClaimed(address indexed user, uint256 amount); + event PlacePrediction(address indexed user,uint256 value, uint256 predictionPoints, address predictionAsset,uint256 prediction,uint256 indexed marketIndex); + event DisputeRaised(uint256 indexed marketIndex, address raisedBy, uint256 proposalId, uint256 proposedValue); + event DisputeResolved(uint256 indexed marketIndex, bool status); + event ReferralLog(address indexed referrer, address indexed referee, uint256 referredOn); + + struct PredictionData { + uint64 predictionPoints; + uint64 amountStaked; + } + + struct UserMarketData { + bool claimedReward; + bool predictedWithBlot; + bool multiplierApplied; + mapping(uint => PredictionData) predictionData; + } + + struct UserData { + uint128 totalStaked; + uint128 lastClaimedIndex; + uint[] marketsParticipated; + uint unusedBalance; + uint referrerFee; + uint refereeFee; + address referrer; + mapping(uint => UserMarketData) userMarketData; + } + + + struct MarketBasicData { + uint32 Mtype; + uint32 currency; + uint32 startTime; + uint32 predictionTime; + uint64 neutralMinValue; + uint64 neutralMaxValue; + address feedAddress; + } + + struct MarketDataExtended { + uint32 WinningOption; + uint32 settleTime; + address disputeRaisedBy; + uint64 disputeStakeAmount; + uint incentiveToDistribute; + uint rewardToDistribute; + uint totalStaked; + PredictionStatus predictionStatus; + } + + struct MarketTypeData { + uint32 predictionTime; + uint32 optionRangePerc; + uint32 cooldownTime; + bool paused; + uint32 minTimePassed; + } + + struct MarketCurrency { + bytes32 currencyName; + address marketFeed; + uint8 decimals; + uint8 roundOfToNearest; + } + + struct MarketCreationData { + uint32 initialStartTime; + uint64 latestMarket; + uint64 penultimateMarket; + bool paused; + } + + struct PricingData { + uint256 stakingFactorMinStake; + uint32 stakingFactorWeightage; + uint32 currentPriceWeightage; + uint32 minTimePassed; + } + + struct MarketFeeParams { + uint32 cummulativeFeePercent; + uint32 daoCommissionPercent; + uint32 referrerFeePercent; + uint32 refereeFeePercent; + uint32 marketCreatorFeePercent; + mapping (uint256 => uint64) daoFee; + mapping (uint256 => uint64) marketCreatorFee; + } + + MarketFeeParams internal marketFeeParams; + uint64 internal mcDefaultPredictionAmount; + mapping (address => uint256) public relayerFeeEarned; + mapping(uint256 => PricingData) internal marketPricingData; + + + address internal plotToken; + + address internal predictionToken; + + ITokenController internal tokenController; + IMarketUtility internal marketUtility; + IMarketCreationRewards internal marketCreationRewards; + + address internal authorizedMultiSig; + uint internal totalOptions; + uint internal predictionDecimalMultiplier; + uint internal defaultMaxRecords; + + bool public marketCreationPaused; + MarketCurrency[] internal marketCurrencies; + MarketTypeData[] internal marketTypeArray; + mapping(bytes32 => uint) internal marketCurrency; + + mapping(uint64 => uint32) internal marketType; + mapping(uint256 => mapping(uint256 => MarketCreationData)) internal marketCreationData; + + MarketBasicData[] internal marketBasicData; + + mapping(uint256 => MarketDataExtended) internal marketDataExtended; + mapping(address => UserData) internal userData; + + mapping(uint =>mapping(uint=>PredictionData)) internal marketOptionsAvailable; + mapping(uint256 => uint256) internal disputeProposalId; + + function setReferrer(address _referrer, address _referee) external { + require(marketUtility.isAuthorized(msg.sender)); + UserData storage _userData = userData[_referee]; + require(_userData.totalStaked == 0); + require(_userData.referrer == address(0)); + _userData.referrer = _referrer; + emit ReferralLog(_referrer, _referee, now); + } + + /** + * @dev Get fees earned by participating in the referral program + * @param _user Address of the user + * @return _referrerFee Fees earned by referring other users + * @return _refereeFee Fees earned if referred by some one + */ + function getReferralFees(address _user) external view returns(uint256 _referrerFee, uint256 _refereeFee) { + UserData storage _userData = userData[_user]; + return (_userData.referrerFee, _userData.refereeFee); + } + + function claimReferralFee(address _user) external { + UserData storage _userData = userData[_user]; + uint256 _referrerFee = _userData.referrerFee; + delete _userData.referrerFee; + uint256 _refereeFee = _userData.refereeFee; + delete _userData.refereeFee; + _transferAsset(predictionToken, _user, (_refereeFee.add(_referrerFee)).mul(10**predictionDecimalMultiplier)); + } + + /** + * @dev Add new market currency. + * @param _currencyName name of the currency + * @param _marketFeed Price Feed address of the currency + * @param decimals Decimals of the price provided by feed address + * @param roundOfToNearest Round of the price to nearest number + * @param _marketStartTime Start time of initial markets + */ + function addMarketCurrency(bytes32 _currencyName, address _marketFeed, uint8 decimals, uint8 roundOfToNearest, uint32 _marketStartTime) external onlyAuthorizedToGovern { + require((marketCurrencies[marketCurrency[_currencyName]].currencyName != _currencyName)); + require(decimals != 0); + require(roundOfToNearest != 0); + _addMarketCurrency(_currencyName, _marketFeed, decimals, roundOfToNearest, _marketStartTime); + } + + function _addMarketCurrency(bytes32 _currencyName, address _marketFeed, uint8 decimals, uint8 roundOfToNearest, uint32 _marketStartTime) internal { + uint32 index = uint32(marketCurrencies.length); + marketCurrency[_currencyName] = index; + marketCurrencies.push(MarketCurrency(_currencyName, _marketFeed, decimals, roundOfToNearest)); + emit MarketCurrencies(index, _marketFeed, _currencyName, true); + for(uint32 i = 0;i < marketTypeArray.length; i++) { + marketCreationData[i][index].initialStartTime = _marketStartTime; + } + } + + /** + * @dev Add new market type. + * @param _predictionTime The time duration of market. + * @param _optionRangePerc Option range percent of neutral min, max options (raised by 2 decimals) + * @param _marketCooldownTime Cool down time of the market after market is settled + */ + function addMarketType(uint32 _predictionTime, uint32 _optionRangePerc, uint32 _marketStartTime, uint32 _marketCooldownTime, uint32 _minTimePassed) external onlyAuthorizedToGovern { + require(marketTypeArray[marketType[_predictionTime]].predictionTime != _predictionTime); + require(_predictionTime > 0); + require(_optionRangePerc > 0); + require(_marketCooldownTime > 0); + require(_minTimePassed > 0); + uint32 index = _addMarketType(_predictionTime, _optionRangePerc, _marketCooldownTime, _minTimePassed); + for(uint32 i = 0;i < marketCurrencies.length; i++) { + marketCreationData[index][i].initialStartTime = _marketStartTime; + } + } + + function _addMarketType(uint32 _predictionTime, uint32 _optionRangePerc, uint32 _marketCooldownTime, uint32 _minTimePassed) internal returns(uint32) { + uint32 index = uint32(marketTypeArray.length); + marketType[_predictionTime] = index; + marketTypeArray.push(MarketTypeData(_predictionTime, _optionRangePerc, _marketCooldownTime, false, _minTimePassed)); + emit MarketTypes(index, _predictionTime, _marketCooldownTime, _optionRangePerc, true, _minTimePassed); + return index; + } + + function updateMarketType(uint32 _marketType, uint32 _optionRangePerc, uint32 _marketCooldownTime, uint32 _minTimePassed) external onlyAuthorizedToGovern { + require(_optionRangePerc > 0); + require(_marketCooldownTime > 0); + MarketTypeData storage _marketTypeArray = marketTypeArray[_marketType]; + require(_marketTypeArray.predictionTime != 0); + _marketTypeArray.optionRangePerc = _optionRangePerc; + _marketTypeArray.cooldownTime = _marketCooldownTime; + _marketTypeArray.minTimePassed = _minTimePassed; + emit MarketTypes(_marketType, _marketTypeArray.predictionTime, _marketCooldownTime, _optionRangePerc, true, _minTimePassed); + } + + /** + * @dev function to update integer parameters + */ + function updateUintParameters(bytes8 code, uint256 value) external onlyAuthorizedToGovern { + if(code == "CMFP") { // Cummulative fee percent + marketFeeParams.cummulativeFeePercent = uint32(value); + } else if(code == "DAOF") { // DAO Fee percent in Cummulative fee + marketFeeParams.daoCommissionPercent = uint32(value); + } else if(code == "RFRRF") { // Referrer fee percent in Cummulative fee + marketFeeParams.referrerFeePercent = uint32(value); + } else if(code == "RFREF") { // Referee fee percent in Cummulative fee + marketFeeParams.refereeFeePercent = uint32(value); + } else if(code == "MCF") { // Market Creator fee percent in Cummulative fee + marketFeeParams.marketCreatorFeePercent = uint32(value); + } else if(code == "MDPA") { // Market creators default prediction amount + mcDefaultPredictionAmount = uint64(value); + } + } + + /** + * @dev function to get integer parameters + */ + function getUintParameters(bytes8 code) external view returns(bytes8 codeVal, uint256 value) { + codeVal = code; + if(code == "CMFP") { // Cummulative fee percent + value = marketFeeParams.cummulativeFeePercent; + } else if(code == "DAOF") { // DAO Fee percent in Cummulative fee + value = marketFeeParams.daoCommissionPercent; + } else if(code == "RFRRF") { // Referrer fee percent in Cummulative fee + value = marketFeeParams.referrerFeePercent; + } else if(code == "RFREF") { // Referee fee percent in Cummulative fee + value = marketFeeParams.refereeFeePercent; + } else if(code == "MCF") { // Market Creator fee percent in Cummulative fee + value = marketFeeParams.marketCreatorFeePercent; + } else if(code == "MDPA") { // Market creators default prediction amount + value = mcDefaultPredictionAmount; + } + } + + /** + * @dev Changes the master address and update it's instance + */ + function setMasterAddress() public { + OwnedUpgradeabilityProxy proxy = OwnedUpgradeabilityProxy(address(uint160(address(this)))); + require(msg.sender == proxy.proxyOwner()); + IMaster ms = IMaster(msg.sender); + masterAddress = msg.sender; + address _plotToken = ms.dAppToken(); + plotToken = _plotToken; + predictionToken = _plotToken; + governance = IGovernance(ms.getLatestAddress("GV")); + tokenController = ITokenController(ms.getLatestAddress("TC")); + } + + /** + * @dev Start the initial market and set initial variables. + */ + function addInitialMarketTypesAndStart(uint32 _marketStartTime, address _ethFeed, address _btcFeed, address _multiSig) external { + require(marketTypeArray.length == 0); + require(_ethFeed != address(0)); + require(_btcFeed != address(0)); + require(_multiSig != address(0)); + + IMaster ms = IMaster(masterAddress); + marketCreationRewards = IMarketCreationRewards(ms.getLatestAddress("MC")); + marketUtility = IMarketUtility(ms.getLatestAddress("MU")); + require(marketUtility.isAuthorized(msg.sender)); + + authorizedMultiSig = _multiSig; + totalOptions = 3; + predictionDecimalMultiplier = 10; + defaultMaxRecords = 20; + MarketFeeParams storage _marketFeeParams = marketFeeParams; + _marketFeeParams.cummulativeFeePercent = 200; + _marketFeeParams.daoCommissionPercent = 1000; + _marketFeeParams.refereeFeePercent = 1000; + _marketFeeParams.referrerFeePercent = 2000; + _marketFeeParams.marketCreatorFeePercent = 4000; + mcDefaultPredictionAmount = 100 * 10**8; + + _addMarketType(4 hours, 100, 1 hours, 40 minutes); + _addMarketType(24 hours, 200, 6 hours, 4 hours); + _addMarketType(168 hours, 500, 8 hours, 28 hours); + + _addMarketCurrency("ETH/USD", _ethFeed, 8, 1, _marketStartTime); + _addMarketCurrency("BTC/USD", _btcFeed, 8, 25, _marketStartTime); + + marketBasicData.push(MarketBasicData(0,0,0, 0,0,0, address(0))); + for(uint32 i = 0;i < marketTypeArray.length; i++) { + createMarket(0, i); + createMarket(1, i); + } + _initializeEIP712("AM"); + } + + /** + * @dev Create the market. + * @param _marketCurrencyIndex The index of market currency feed + * @param _marketTypeIndex The time duration of market. + */ + function createMarket(uint32 _marketCurrencyIndex,uint32 _marketTypeIndex) public { + MarketTypeData storage _marketType = marketTypeArray[_marketTypeIndex]; + require(!marketCreationPaused && !_marketType.paused); + _closePreviousMarket( _marketTypeIndex, _marketCurrencyIndex); + // marketUtility.update(); + uint32 _startTime = calculateStartTimeForMarket(_marketCurrencyIndex, _marketTypeIndex); + (uint64 _minValue, uint64 _maxValue) = marketUtility.calculateOptionRange(_marketType.optionRangePerc, marketCurrencies[_marketCurrencyIndex].decimals, marketCurrencies[_marketCurrencyIndex].roundOfToNearest, marketCurrencies[_marketCurrencyIndex].marketFeed, marketCurrencies[_marketCurrencyIndex].currencyName); + uint64 _marketIndex = uint64(marketBasicData.length); + marketBasicData.push(MarketBasicData(_marketTypeIndex,_marketCurrencyIndex,_startTime, _marketType.predictionTime,_minValue,_maxValue, marketCurrencies[_marketCurrencyIndex].marketFeed)); + MarketCreationData storage _marketCreationData = marketCreationData[_marketTypeIndex][_marketCurrencyIndex]; + (_marketCreationData.penultimateMarket, _marketCreationData.latestMarket) = + (_marketCreationData.latestMarket, _marketIndex); + (uint256 _stakingFactorMinStake, uint32 _stakingFactorWeightage, uint32 _currentPriceWeightage) = marketUtility.getPriceCalculationParams(); + marketPricingData[_marketIndex] = PricingData(_stakingFactorMinStake, _stakingFactorWeightage, _currentPriceWeightage, _marketType.minTimePassed); + emit MarketQuestion(_marketIndex, marketCurrencies[_marketCurrencyIndex].currencyName, _marketTypeIndex, _startTime, _marketType.predictionTime, _minValue, _maxValue); + emit OptionPricingParams(_marketIndex, _stakingFactorMinStake,_stakingFactorWeightage,_currentPriceWeightage,marketPricingData[_marketIndex].minTimePassed); + address _msgSenderAddress = _msgSender(); + marketCreationRewards.calculateMarketCreationIncentive(_msgSenderAddress, _marketIndex); + _placeInitialPrediction(_marketIndex, _msgSenderAddress); + } + + function _placeInitialPrediction(uint64 _marketId, address _msgSenderAddress) internal { + uint256 _defaultAmount = (10**predictionDecimalMultiplier).mul(mcDefaultPredictionAmount); + (uint _tokenLeft, uint _tokenReward) = getUserUnusedBalance(_msgSenderAddress); + if(_tokenLeft.add(_tokenReward) < _defaultAmount) { + _deposit(_defaultAmount); + } + + _placePrediction(_marketId, predictionToken, mcDefaultPredictionAmount/3, 1); + _placePrediction(_marketId, predictionToken, mcDefaultPredictionAmount/3, 2); + _placePrediction(_marketId, predictionToken, mcDefaultPredictionAmount - 2*(mcDefaultPredictionAmount/3), 3); + } + + /** + * @dev Calculate start time for next market of provided currency and market type indexes + */ + function calculateStartTimeForMarket(uint32 _marketCurrencyIndex, uint32 _marketType) public view returns(uint32 _marketStartTime) { + _marketStartTime = marketCreationData[_marketType][_marketCurrencyIndex].initialStartTime; + uint predictionTime = marketTypeArray[_marketType].predictionTime; + if(now > (predictionTime) + (_marketStartTime)) { + uint noOfMarketsCycles = ((now) - (_marketStartTime)) / (predictionTime); + _marketStartTime = uint32((noOfMarketsCycles * (predictionTime)) + (_marketStartTime)); + } + } + + /** + * @dev Transfer the _asset to specified address. + * @param _recipient The address to transfer the asset of + * @param _amount The amount which is transfer. + */ + function _transferAsset(address _asset, address _recipient, uint256 _amount) internal { + if(_amount > 0) { + require(IToken(_asset).transfer(_recipient, _amount)); + } + } + + /** + * @dev Internal function to settle the previous market + */ + function _closePreviousMarket(uint64 _marketTypeIndex, uint64 _marketCurrencyIndex) internal { + MarketCreationData storage _marketCreationData = marketCreationData[_marketTypeIndex][_marketCurrencyIndex]; + uint64 currentMarket = _marketCreationData.latestMarket; + if(currentMarket != 0) { + require(marketStatus(currentMarket) >= PredictionStatus.InSettlement); + uint64 penultimateMarket = _marketCreationData.penultimateMarket; + if(penultimateMarket > 0 && now >= marketSettleTime(penultimateMarket)) { + _settleMarket(penultimateMarket); + } + } + } + + /** + * @dev Get market settle time + * @return the time at which the market result will be declared + */ + function marketSettleTime(uint256 _marketId) public view returns(uint32) { + if(marketDataExtended[_marketId].settleTime > 0) { + return marketDataExtended[_marketId].settleTime; + } + return marketBasicData[_marketId].startTime + (marketBasicData[_marketId].predictionTime * 2); + } + + /** + * @dev Gets the status of market. + * @return PredictionStatus representing the status of market. + */ + function marketStatus(uint256 _marketId) public view returns(PredictionStatus){ + MarketDataExtended storage _marketDataExtended = marketDataExtended[_marketId]; + if(_marketDataExtended.predictionStatus == PredictionStatus.Live && now >= marketExpireTime(_marketId)) { + return PredictionStatus.InSettlement; + } else if(_marketDataExtended.predictionStatus == PredictionStatus.Settled && now <= marketCoolDownTime(_marketId)) { + return PredictionStatus.Cooling; + } + return _marketDataExtended.predictionStatus; + } + + /** + * @dev Get market cooldown time + * @return the time upto which user can raise the dispute after the market is settled + */ + function marketCoolDownTime(uint256 _marketId) public view returns(uint256) { + return (marketSettleTime(_marketId) + marketTypeArray[marketBasicData[_marketId].Mtype].cooldownTime); + } + + /** + * @dev Updates Flag to pause creation of market. + */ + function pauseMarketCreation() external onlyAuthorizedToGovern { + require(!marketCreationPaused); + marketCreationPaused = true; + } + + /** + * @dev Updates Flag to resume creation of market. + */ + function resumeMarketCreation() external onlyAuthorizedToGovern { + require(marketCreationPaused); + marketCreationPaused = false; + } + + /** + * @dev Set the flag to pause/resume market creation of particular market type + */ + function toggleMarketCreationType(uint64 _marketTypeIndex, bool _flag) external onlyAuthorizedToGovern { + require(marketTypeArray[_marketTypeIndex].paused != _flag); + marketTypeArray[_marketTypeIndex].paused = _flag; + } + + /** + * @dev Function to deposit prediction token for participation in markets + * @param _amount Amount of prediction token to deposit + */ + function _deposit(uint _amount) internal { + address payable _msgSenderAddress = _msgSender(); + _transferTokenFrom(predictionToken, _msgSenderAddress, address(this), _amount); + userData[_msgSenderAddress].unusedBalance = userData[_msgSenderAddress].unusedBalance.add(_amount); + emit Deposited(_msgSenderAddress, _amount, now); + } + + /** + * @dev Withdraw provided amount of deposited and available prediction token + * @param _token Amount of prediction token to withdraw + * @param _maxRecords Maximum number of records to check + */ + function withdraw(uint _token, uint _maxRecords) public { + (uint _tokenLeft, uint _tokenReward) = getUserUnusedBalance(_msgSender()); + _tokenLeft = _tokenLeft.add(_tokenReward); + _withdraw(_token, _maxRecords, _tokenLeft); + } + + /** + * @dev Internal function to withdraw deposited and available assets + * @param _token Amount of prediction token to withdraw + * @param _maxRecords Maximum number of records to check + * @param _tokenLeft Amount of prediction token left unused for user + */ + function _withdraw(uint _token, uint _maxRecords, uint _tokenLeft) internal { + address payable _msgSenderAddress = _msgSender(); + _withdrawReward(_maxRecords); + userData[_msgSenderAddress].unusedBalance = _tokenLeft.sub(_token); + require(_token > 0); + _transferAsset(predictionToken, _msgSenderAddress, _token); + emit Withdrawn(_msgSenderAddress, _token, now); + } + + /** + * @dev Get market expire time + * @return the time upto which user can place predictions in market + */ + function marketExpireTime(uint _marketId) internal view returns(uint256) { + return marketBasicData[_marketId].startTime + (marketBasicData[_marketId].predictionTime); + } + + /** + * @dev Deposit and Place prediction on the available options of the market. + * @param _marketId Index of the market + * @param _tokenDeposit prediction token amount to deposit + * @param _asset The asset used by user during prediction whether it is prediction token address or in Bonus token. + * @param _predictionStake The amount staked by user at the time of prediction. + * @param _prediction The option on which user placed prediction. + * _tokenDeposit should be passed with 18 decimals + * _predictioStake should be passed with 8 decimals, reduced it to 8 decimals to reduce the storage space of prediction data + */ + function depositAndPlacePrediction(uint _tokenDeposit, uint _marketId, address _asset, uint64 _predictionStake, uint256 _prediction) external { + if(_tokenDeposit > 0) { + _deposit(_tokenDeposit); + } + _placePrediction(_marketId, _asset, _predictionStake, _prediction); + } + + /** + * @dev Place prediction on the available options of the market. + * @param _marketId Index of the market + * @param _asset The asset used by user during prediction whether it is prediction token address or in Bonus token. + * @param _predictionStake The amount staked by user at the time of prediction. + * @param _prediction The option on which user placed prediction. + * _predictioStake should be passed with 8 decimals, reduced it to 8 decimals to reduce the storage space of prediction data + */ + function _placePrediction(uint _marketId, address _asset, uint64 _predictionStake, uint256 _prediction) internal { + address payable _msgSenderAddress = _msgSender(); + require(!marketCreationPaused && _prediction <= totalOptions && _prediction >0); + require(now >= marketBasicData[_marketId].startTime && now <= marketExpireTime(_marketId)); + uint64 _predictionStakePostDeduction = _predictionStake; + uint decimalMultiplier = 10**predictionDecimalMultiplier; + UserData storage _userData = userData[_msgSenderAddress]; + if(_asset == predictionToken) { + uint256 unusedBalance = _userData.unusedBalance; + unusedBalance = unusedBalance.div(decimalMultiplier); + if(_predictionStake > unusedBalance) + { + _withdrawReward(defaultMaxRecords); + unusedBalance = _userData.unusedBalance; + unusedBalance = unusedBalance.div(decimalMultiplier); + } + require(_predictionStake <= unusedBalance); + _userData.unusedBalance = (unusedBalance.sub(_predictionStake)).mul(decimalMultiplier); + } else { + require(_asset == tokenController.bLOTToken()); + require(!_userData.userMarketData[_marketId].predictedWithBlot); + _userData.userMarketData[_marketId].predictedWithBlot = true; + tokenController.swapBLOT(_msgSenderAddress, address(this), (decimalMultiplier).mul(_predictionStake)); + _asset = plotToken; + } + _predictionStakePostDeduction = _deductFee(_marketId, _predictionStake, _msgSenderAddress); + + uint64 predictionPoints = _calculatePredictionPointsAndMultiplier(_msgSenderAddress, _marketId, _prediction, _predictionStakePostDeduction); + require(predictionPoints > 0); + + _storePredictionData(_marketId, _prediction, _predictionStakePostDeduction, predictionPoints); + emit PlacePrediction(_msgSenderAddress, _predictionStake, predictionPoints, _asset, _prediction, _marketId); + } + + function _deductFee(uint _marketId, uint64 _amount, address _msgSenderAddress) internal returns(uint64 _amountPostFee){ + uint64 _fee; + address _relayer; + if(_msgSenderAddress != tx.origin) { + _relayer = tx.origin; + } else { + _relayer = _msgSenderAddress; + } + MarketFeeParams storage _marketFeeParams = marketFeeParams; + _fee = _calculateAmulBdivC(_marketFeeParams.cummulativeFeePercent, _amount, 10000); + _amountPostFee = _amount.sub(_fee); + (uint64 _referrerFee, uint64 _refereeFee) = _calculateReferalFee(_msgSenderAddress, _fee, _marketFeeParams.refereeFeePercent, _marketFeeParams.referrerFeePercent); + uint64 _daoFee = _calculateAmulBdivC(_marketFeeParams.daoCommissionPercent, _fee, 10000); + uint64 _marketCreatorFee = _calculateAmulBdivC(_marketFeeParams.marketCreatorFeePercent, _fee, 10000); + _marketFeeParams.daoFee[_marketId] = _marketFeeParams.daoFee[_marketId].add(_daoFee); + _marketFeeParams.marketCreatorFee[_marketId] = _marketFeeParams.marketCreatorFee[_marketId].add(_marketCreatorFee); + _fee = _fee.sub(_daoFee).sub(_referrerFee).sub(_refereeFee).sub(_marketCreatorFee); + relayerFeeEarned[_relayer] = relayerFeeEarned[_relayer].add(_fee); + // _transferAsset(predictionToken, address(marketCreationRewards), (10**predictionDecimalMultiplier).mul(_daoFee)); + } + + function _calculateReferalFee(address _msgSenderAddress, uint64 _cummulativeFee, uint32 _refereeFeePerc, uint32 _referrerFeePerc) internal returns(uint64 _referrerFee, uint64 _refereeFee) { + UserData storage _userData = userData[_msgSenderAddress]; + address _referrer = _userData.referrer; + if(_referrer != address(0)) { + //Commission for referee + _refereeFee = _calculateAmulBdivC(_refereeFeePerc, _cummulativeFee, 10000); + _userData.refereeFee = _userData.refereeFee.add(_refereeFee); + //Commission for referrer + _referrerFee = _calculateAmulBdivC(_referrerFeePerc, _cummulativeFee, 10000); + userData[_referrer].referrerFee = userData[_referrer].referrerFee.add(_referrerFee); + } + } + + /** + * @dev Internal function to calculate prediction points and multiplier + */ + function _calculatePredictionPointsAndMultiplier(address _user, uint256 _marketId, uint256 _prediction, uint64 _stake) internal returns(uint64 predictionPoints){ + bool isMultiplierApplied; + UserData storage _userData = userData[_user]; + (predictionPoints, isMultiplierApplied) = marketUtility.calculatePredictionPoints(_marketId, _prediction, _user, _userData.userMarketData[_marketId].multiplierApplied, _stake); + if(isMultiplierApplied) { + _userData.userMarketData[_marketId].multiplierApplied = true; + } + } + + /** + * @dev Settle the market, setting the winning option + */ + function settleMarket(uint256 _marketId) external { + _settleMarket(_marketId); + } + + /** + * @dev Settle the market explicitly by manually passing the price of market currency + * @param _marketId Index of market + * @param _marketSettleValue The current price of market currency. + */ + function postMarketResult(uint256 _marketId, uint256 _marketSettleValue) external { + require(msg.sender == authorizedMultiSig); + require(marketBasicData[_marketId].feedAddress == address(0)); + if(marketStatus(_marketId) == PredictionStatus.InSettlement) { + _postResult(_marketSettleValue, 0, _marketId); + } + } + + /** + * @dev Settle the market, setting the winning option + */ + function _settleMarket(uint256 _marketId) internal { + address _feedAdd = marketCurrencies[marketBasicData[_marketId].currency].marketFeed; + if(marketStatus(_marketId) == PredictionStatus.InSettlement && _feedAdd != address(0)) { + (uint256 _value, uint256 _roundId) = marketUtility.getSettlemetPrice(_feedAdd, marketSettleTime(_marketId)); + _postResult(_value, _roundId, _marketId); + } + } + + /** + * @dev Calculate the result of market. + * @param _value The current price of market currency. + * @param _roundId Chainlink round Id + * @param _marketId Index of market + */ + function _postResult(uint256 _value, uint256 _roundId, uint256 _marketId) internal { + require(now >= marketSettleTime(_marketId)); + require(_value > 0); + MarketDataExtended storage _marketDataExtended = marketDataExtended[_marketId]; + MarketBasicData storage _marketBasicData = marketBasicData[_marketId]; + if(_marketDataExtended.predictionStatus != PredictionStatus.InDispute) { + _marketDataExtended.settleTime = uint32(now); + uint64 amountToTransfer; + amountToTransfer = (marketFeeParams.daoFee[_marketId]).add(marketFeeParams.marketCreatorFee[_marketId]); + _transferAsset(predictionToken, address(marketCreationRewards), (10**predictionDecimalMultiplier).mul(amountToTransfer)); + marketCreationRewards.depositMarketCreationReward(_marketId, (10**predictionDecimalMultiplier).mul(amountToTransfer)); + } else { + delete _marketDataExtended.settleTime; + } + _setMarketStatus(_marketId, PredictionStatus.Settled); + uint32 _winningOption; + if(_value < _marketBasicData.neutralMinValue) { + _winningOption = 1; + } else if(_value > _marketBasicData.neutralMaxValue) { + _winningOption = 3; + } else { + _winningOption = 2; + } + _marketDataExtended.WinningOption = _winningOption; + // uint64 predictionPointsOnWinningOption = marketOptionsAvailable[_marketId][_winningOption].predictionPoints; + uint64 totalReward = _calculateRewardTally(_marketId, _winningOption); + // (uint64 _rewardPoolShare, bool _thresholdReached) = marketCreationRewards.getMarketCreatorRPoolShareParams(_marketId, tokenParticipation); + // if(_thresholdReached) { + // if( + // predictionPointsOnWinningOption == 0 + // ){ + // marketCreatorIncentive = _calculateAmulBdivC(_rewardPoolShare, tokenParticipation, 10000); + // tokenParticipation = tokenParticipation.sub(marketCreatorIncentive); + // } else { + // marketCreatorIncentive = _calculateAmulBdivC(_rewardPoolShare, totalReward, 10000); + // totalReward = totalReward.sub(marketCreatorIncentive); + // tokenParticipation = 0; + // } + // } + // else { + // // if( + // // predictionPointsOnWinningOption > 0 + // // ){ + // tokenParticipation = 0; + // // } + // } + _marketDataExtended.rewardToDistribute = totalReward; + // _transferAsset(predictionToken, address(marketCreationRewards), (10**predictionDecimalMultiplier).mul(marketCreatorIncentive)); + // marketCreationRewards.depositMarketRewardPoolShare(_marketId, (10**predictionDecimalMultiplier).mul(marketCreatorIncentive), tokenParticipation); + emit MarketResult(_marketId, _marketDataExtended.rewardToDistribute, _winningOption, _value, _roundId, marketFeeParams.daoFee[_marketId], marketFeeParams.marketCreatorFee[_marketId]); + } + + /** + * @dev Internal function to calculate the reward. + * @param _marketId Index of market + * @param _winningOption WinningOption of market + */ + function _calculateRewardTally(uint256 _marketId, uint256 _winningOption) internal view returns(uint64 totalReward){ + for(uint i=1;i <= totalOptions;i++){ + uint64 _tokenStakedOnOption = marketOptionsAvailable[_marketId][i].amountStaked; + if(i != _winningOption) { + totalReward = totalReward.add(_tokenStakedOnOption); + } + } + } + + /** + * @dev Claim fees earned by the relayer address + */ + function claimRelayerRewards() external { + uint _decimalMultiplier = 10**predictionDecimalMultiplier; + address _relayer = msg.sender; + uint256 _fee = (_decimalMultiplier).mul(relayerFeeEarned[_relayer]); + delete relayerFeeEarned[_relayer]; + require(_fee > 0); + _transferAsset(predictionToken, _relayer, _fee); + } + + /** + * @dev Claim the pending return of the market. + * @param maxRecords Maximum number of records to claim reward for + */ + function _withdrawReward(uint256 maxRecords) internal { + address payable _msgSenderAddress = _msgSender(); + uint256 i; + UserData storage _userData = userData[_msgSenderAddress]; + uint len = _userData.marketsParticipated.length; + uint lastClaimed = len; + uint count; + uint tokenReward =0 ; + require(!marketCreationPaused); + for(i = _userData.lastClaimedIndex; i < len && count < maxRecords; i++) { + (uint claimed, uint tempTokenReward) = claimReturn(_msgSenderAddress, _userData.marketsParticipated[i]); + if(claimed > 0) { + delete _userData.marketsParticipated[i]; + tokenReward = tokenReward.add(tempTokenReward); + count++; + } else { + if(lastClaimed == len) { + lastClaimed = i; + } + } + } + if(lastClaimed == len) { + lastClaimed = i; + } + emit ReturnClaimed(_msgSenderAddress, tokenReward); + _userData.unusedBalance = _userData.unusedBalance.add(tokenReward.mul(10**predictionDecimalMultiplier)); + _userData.lastClaimedIndex = uint128(lastClaimed); + } + + /** + * @dev FUnction to return users unused deposited balance including the return earned in markets + * @param _user Address of user + * return prediction token Unused in deposit + * return prediction token Return from market + */ + function getUserUnusedBalance(address _user) public view returns(uint256, uint256){ + uint tokenReward; + uint decimalMultiplier = 10**predictionDecimalMultiplier; + UserData storage _userData = userData[_user]; + uint len = _userData.marketsParticipated.length; + for(uint i = _userData.lastClaimedIndex; i < len; i++) { + tokenReward = tokenReward.add(getReturn(_user, _userData.marketsParticipated[i])); + } + return (_userData.unusedBalance, tokenReward.mul(decimalMultiplier)); + } + + /** + * @dev Gets number of positions user got in prediction + * @param _user Address of user + * @param _marketId Index of market + * @param _option Option Id + * return Number of positions user got in prediction + */ + function getUserPredictionPoints(address _user, uint256 _marketId, uint256 _option) external view returns(uint64) { + return userData[_user].userMarketData[_marketId].predictionData[_option].predictionPoints; + } + + /** + * @dev Gets the market data. + * @return _marketCurrency returns the currency name of the market. + * @return neutralMinValue Neutral min value deciding the option ranges of market + * @return neutralMaxValue Neutral max value deciding the option ranges of market + * @return _optionPrice uint[] memory representing the option price of each option ranges of the market. + * @return _tokenStaked uint[] memory representing the prediction token 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 getMarketData(uint256 _marketId) external view returns + (bytes32 _marketCurrency,uint neutralMinValue,uint neutralMaxValue, uint[] memory _tokenStaked,uint _predictionTime,uint _expireTime, PredictionStatus _predictionStatus){ + MarketBasicData storage _marketBasicData = marketBasicData[_marketId]; + _marketCurrency = marketCurrencies[_marketBasicData.currency].currencyName; + _predictionTime = _marketBasicData.predictionTime; + _expireTime =marketExpireTime(_marketId); + _predictionStatus = marketStatus(_marketId); + neutralMinValue = _marketBasicData.neutralMinValue; + neutralMaxValue = _marketBasicData.neutralMaxValue; + + _tokenStaked = new uint[](totalOptions); + for (uint i = 0; i < totalOptions; i++) { + _tokenStaked[i] = marketOptionsAvailable[_marketId][i+1].amountStaked; + } + } + + /** + * @dev Claim the return amount of the specified address. + * @param _user User address + * @param _marketId Index of market + * @return Flag, if 0:cannot claim, 1: Already Claimed, 2: Claimed; Return in prediction token + */ + function claimReturn(address payable _user, uint _marketId) internal returns(uint256, uint256) { + + if(marketStatus(_marketId) != PredictionStatus.Settled) { + return (0, 0); + } + UserData storage _userData = userData[_user]; + if(_userData.userMarketData[_marketId].claimedReward) { + return (1, 0); + } + _userData.userMarketData[_marketId].claimedReward = true; + return (2, getReturn(_user, _marketId)); + } + + /** + * @dev Gets the return amount of the specified address. + * @param _user The address to specify the return of + * @param _marketId Index of market + * @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, uint _marketId) public view returns (uint returnAmount){ + if(marketStatus(_marketId) != PredictionStatus.Settled || getTotalPredictionPoints(_marketId) == 0) { + return (returnAmount); + } + uint256 _winningOption = marketDataExtended[_marketId].WinningOption; + UserData storage _userData = userData[_user]; + returnAmount = _userData.userMarketData[_marketId].predictionData[_winningOption].amountStaked; + uint256 userPredictionPointsOnWinngOption = _userData.userMarketData[_marketId].predictionData[_winningOption].predictionPoints; + if(userPredictionPointsOnWinngOption > 0) { + returnAmount = _addUserReward(_marketId, returnAmount, _winningOption, userPredictionPointsOnWinngOption); + } + return returnAmount; + } + + /** + * @dev Adds the reward in the total return of the specified address. + * @param returnAmount The return amount. + * @return uint[] memory representing the return amount after adding reward. + */ + function _addUserReward(uint256 _marketId, uint returnAmount, uint256 _winningOption, uint256 _userPredictionPointsOnWinngOption) internal view returns(uint){ + return returnAmount.add( + _userPredictionPointsOnWinngOption.mul(marketDataExtended[_marketId].rewardToDistribute).div(marketOptionsAvailable[_marketId][_winningOption].predictionPoints) + ); + } + + /** + * @dev Basic function to perform mathematical operation of (`_a` * `_b` / `_c`) + * @param _a value of variable a + * @param _b value of variable b + * @param _c value of variable c + */ + function _calculateAmulBdivC(uint64 _a, uint64 _b, uint64 _c) internal pure returns(uint64) { + return _a.mul(_b).div(_c); + } + + /** + * @dev Returns total assets staked in market in PLOT value + * @param _marketId Index of market + * @return tokenStaked Total prediction token staked on market value in PLOT + */ + function getTotalStakedWorthInPLOT(uint256 _marketId) public view returns(uint256 _tokenStakedWorth) { + uint256 _conversionRate = marketUtility.conversionRate(predictionToken); + return (marketDataExtended[_marketId].totalStaked).mul(_conversionRate).mul(10**predictionDecimalMultiplier); + } + + /** + * @dev Returns total prediction points allocated to users + * @param _marketId Index of market + * @return predictionPoints total prediction points allocated to users + */ + function getTotalPredictionPoints(uint _marketId) public view returns(uint64 predictionPoints) { + for(uint256 i = 1; i<= totalOptions;i++) { + predictionPoints = predictionPoints.add(marketOptionsAvailable[_marketId][i].predictionPoints); + } + } + + /** + * @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 predictionPoints The positions user got during prediction. + */ + function _storePredictionData(uint _marketId, uint _prediction, uint64 _predictionStake, uint64 predictionPoints) internal { + address payable _msgSenderAddress = _msgSender(); + UserData storage _userData = userData[_msgSenderAddress]; + PredictionData storage _predictionData = marketOptionsAvailable[_marketId][_prediction]; + if(!_hasUserParticipated(_marketId, _msgSenderAddress)) { + _userData.marketsParticipated.push(_marketId); + } + _userData.userMarketData[_marketId].predictionData[_prediction].predictionPoints = _userData.userMarketData[_marketId].predictionData[_prediction].predictionPoints.add(predictionPoints); + _predictionData.predictionPoints = _predictionData.predictionPoints.add(predictionPoints); + + _userData.userMarketData[_marketId].predictionData[_prediction].amountStaked = _userData.userMarketData[_marketId].predictionData[_prediction].amountStaked.add(_predictionStake); + _predictionData.amountStaked = _predictionData.amountStaked.add(_predictionStake); + _userData.totalStaked = _userData.totalStaked.add(_predictionStake); + marketDataExtended[_marketId].totalStaked = marketDataExtended[_marketId].totalStaked.add(_predictionStake); + + } + + /** + * @dev Function to check if user had participated in given market + * @param _marketId Index of market + * @param _user Address of user + */ + function _hasUserParticipated(uint256 _marketId, address _user) internal view returns(bool _hasParticipated) { + for(uint i = 1;i <= totalOptions; i++) { + if(userData[_user].userMarketData[_marketId].predictionData[i].predictionPoints > 0) { + _hasParticipated = true; + break; + } + } + } + + /** + * @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 _marketId, uint256 _proposedValue, string memory proposalTitle, string memory description, string memory solutionHash) public { + address payable _msgSenderAddress = _msgSender(); + MarketDataExtended storage _marketDataExtended = marketDataExtended[_marketId]; + require(_marketDataExtended.totalStaked > 0); + require(marketStatus(_marketId) == PredictionStatus.Cooling); + uint _stakeForDispute = marketUtility.getDisputeResolutionParams(); + _transferTokenFrom(plotToken, _msgSenderAddress, address(this), _stakeForDispute); + // marketRegistry.createGovernanceProposal(proposalTitle, description, solutionHash, abi.encode(address(this), proposedValue), _stakeForDispute, msg.sender, ethAmountToPool, tokenAmountToPool, proposedValue); + uint proposalId = governance.getProposalLength(); + // marketBasicData[msg.sender].disputeStakes = DisputeStake(proposalId, _user, _stakeForDispute, _ethSentToPool, _tokenSentToPool); + _marketDataExtended.disputeRaisedBy = _msgSenderAddress; + _marketDataExtended.disputeStakeAmount = uint64(_stakeForDispute.div(10**predictionDecimalMultiplier)); + disputeProposalId[proposalId] = _marketId; + governance.createProposalwithSolution(proposalTitle, proposalTitle, description, 9, solutionHash, abi.encode(_marketId, _proposedValue)); + emit DisputeRaised(_marketId, _msgSenderAddress, proposalId, _proposedValue); + _setMarketStatus(_marketId, PredictionStatus.InDispute); + } + + function _transferTokenFrom(address _token, address _from, address _to, uint256 _amount) internal { + IToken(_token).transferFrom(_from, _to, _amount); + } + + /** + * @dev Resolve the dispute if wrong value passed at the time of market result declaration. + * @param _marketId Index of market. + * @param _result The final proposed result of the market. + */ + function resolveDispute(uint256 _marketId, uint256 _result) external onlyAuthorizedToGovern { + // delete marketCreationRewardData[_marketId].plotIncentive; + // delete marketCreationRewardData[_marketId].ethIncentive; + _resolveDispute(_marketId, true, _result); + emit DisputeResolved(_marketId, true); + MarketDataExtended storage _marketDataExtended = marketDataExtended[_marketId]; + _transferAsset(plotToken, _marketDataExtended.disputeRaisedBy, (10**predictionDecimalMultiplier).mul(_marketDataExtended.disputeStakeAmount)); + } + + /** + * @dev Resolve the dispute + * @param _marketId Index of market. + * @param accepted Flag mentioning if dispute is accepted or not + * @param finalResult The final correct value of market currency. + */ + function _resolveDispute(uint256 _marketId, bool accepted, uint256 finalResult) internal { + require(marketStatus(_marketId) == PredictionStatus.InDispute); + if(accepted) { + _postResult(finalResult, 0, _marketId); + } + _setMarketStatus(_marketId, PredictionStatus.Settled); + } + + /** + * @dev Burns the tokens of member who raised the dispute, if dispute is rejected. + * @param _proposalId Id of dispute resolution proposal + */ + function burnDisputedProposalTokens(uint _proposalId) external onlyAuthorizedToGovern { + uint256 _marketId = disputeProposalId[_proposalId]; + _resolveDispute(_marketId, false, 0); + emit DisputeResolved(_marketId, false); + _transferAsset(plotToken, address(marketCreationRewards), (10**predictionDecimalMultiplier).mul(marketDataExtended[_marketId].disputeStakeAmount)); + // IToken(plotToken).transfer(address(marketCreationRewards),(10**predictionDecimalMultiplier).mul(marketDataExtended[_marketId].disputeStakeAmount)); + } + + /** + * @dev Get flags set for user + * @param _marketId Index of market. + * @param _user User address + * @return Flag defining if user had predicted with bPLOT + * @return Flag defining if user had availed multiplier + */ + function getUserFlags(uint256 _marketId, address _user) external view returns(bool, bool) { + return ( + userData[_user].userMarketData[_marketId].predictedWithBlot, + userData[_user].userMarketData[_marketId].multiplierApplied + ); + } + + /** + * @dev Gets the result of the market. + * @param _marketId Index of 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 prediction token staked on winning option. + */ + function getMarketResults(uint256 _marketId) external view returns(uint256 _winningOption, uint256, uint256, uint256) { + _winningOption = marketDataExtended[_marketId].WinningOption; + return (_winningOption, marketOptionsAvailable[_marketId][_winningOption].predictionPoints, marketDataExtended[_marketId].rewardToDistribute, marketOptionsAvailable[_marketId][_winningOption].amountStaked); + } + + /** + * @dev Internal function set market status + * @param _marketId Index of market + * @param _status Status of market to set + */ + function _setMarketStatus(uint256 _marketId, PredictionStatus _status) internal { + marketDataExtended[_marketId].predictionStatus = _status; + } + + /** + * @dev Gets the Option pricing params for market. + * @param _marketId Index of market. + * @param _option predicting option. + * @return uint[] Array consist of pricing param. + * @return uint32 start time of market. + * @return address feed address for market. + */ + function getMarketOptionPricingParams(uint _marketId, uint _option) external view returns(uint[] memory, uint32,address) { + + // [0] -> amount staked in `_option` + // [1] -> Total amount staked in market + // [2] -> Minimum prediction amount in market needed to kick-in staking factor in option pricing calculation + // [3] -> Weightage given to staking factor in option pricing + // [4] -> Weightage given to Current price factor in option pricing + // [5] -> Till this time, time factor will be same for option pricing + uint[] memory _optionPricingParams = new uint256[](6); + MarketBasicData storage _marketBasicData = marketBasicData[_marketId]; + PricingData storage _marketPricingData = marketPricingData[_marketId]; + _optionPricingParams[0] = marketOptionsAvailable[_marketId][_option].amountStaked; + _optionPricingParams[1] = marketDataExtended[_marketId].totalStaked; + _optionPricingParams[2] = _marketPricingData.stakingFactorMinStake; + _optionPricingParams[3] = _marketPricingData.stakingFactorWeightage; + _optionPricingParams[4] = _marketPricingData.currentPriceWeightage; + _optionPricingParams[5] = _marketPricingData.minTimePassed; + return (_optionPricingParams,_marketBasicData.startTime,_marketBasicData.feedAddress); + } + + /** + * @dev Gets the Feed address for market. + * @ param currencyType currency name. + * @return address feed address for market. + */ + function getMarketCurrencyData(bytes32 currencyType) external view returns(address) { + uint typeIndex = marketCurrency[currencyType]; + MarketCurrency storage _marketCurrency = marketCurrencies[typeIndex]; + // Market currency should be valid + require((_marketCurrency.currencyName == currencyType)); + return (_marketCurrency.marketFeed); + + } + +} diff --git a/contracts/Governance.sol b/contracts/Governance.sol index 554824442..9cd946c8b 100644 --- a/contracts/Governance.sol +++ b/contracts/Governance.sol @@ -20,14 +20,16 @@ import "./external/govblocks-protocol/interfaces/IProposalCategory.sol"; import "./external/govblocks-protocol/interfaces/IMemberRoles.sol"; import "./external/proxy/OwnedUpgradeabilityProxy.sol"; import "./external/openzeppelin-solidity/math/SafeMath.sol"; +import "./external/NativeMetaTransaction.sol"; import "./interfaces/Iupgradable.sol"; -import "./interfaces/IMarketRegistry.sol"; +import "./interfaces/IAllMarkets.sol"; +import "./interfaces/IMarketCreationRewards.sol"; import "./interfaces/ITokenController.sol"; import "./interfaces/IToken.sol"; import "./interfaces/IMaster.sol"; import "./interfaces/IMarket.sol"; -contract Governance is IGovernance, Iupgradable { +contract Governance is IGovernance, Iupgradable, NativeMetaTransaction { using SafeMath for uint256; enum ProposalStatus { @@ -73,7 +75,8 @@ contract Governance is IGovernance, Iupgradable { mapping(address => uint256) public lastRewardClaimed; bytes32 constant swapABMemberHash = keccak256(abi.encodeWithSignature("swapABMember(address,address)")); - bytes32 constant resolveDisputeHash = keccak256(abi.encodeWithSignature("resolveDispute(address,uint256)")); + bytes32 constant resolveDisputeHash = keccak256(abi.encodeWithSignature("resolveDispute(uint256,uint256)")); + uint256 constant totalSupplyCapForDRQrm = 50; bool internal constructorCheck; @@ -89,7 +92,8 @@ contract Governance is IGovernance, Iupgradable { IMaster public ms; IMemberRoles internal memberRole; - IMarketRegistry internal marketRegistry; + IAllMarkets internal allMarkets; + IMarketCreationRewards internal mcr; IProposalCategory internal proposalCategory; //Plot Token Instance IToken internal tokenInstance; @@ -114,17 +118,6 @@ contract Governance is IGovernance, Iupgradable { */ event ActionRejected(uint256 indexed proposalId, address rejectedBy); - /** - * @dev Checks if msg.sender is proposal owner - */ - modifier onlyProposalOwner(uint256 _proposalId) { - require( - msg.sender == allProposalData[_proposalId].owner, - "Not allowed" - ); - _; - } - /** * @dev Checks if proposal is opened for voting */ @@ -172,9 +165,10 @@ contract Governance is IGovernance, Iupgradable { string calldata _proposalDescHash, uint256 _categoryId ) external isAllowed(_categoryId) { + address _msgSenderAddress = _msgSender(); require( memberRole.checkRole( - msg.sender, + _msgSenderAddress, uint256(IMemberRoles.Role.TokenHolder) ), "Not Member" @@ -184,7 +178,8 @@ contract Governance is IGovernance, Iupgradable { _proposalTitle, _proposalSD, _proposalDescHash, - _categoryId + _categoryId, + _msgSenderAddress ); } @@ -202,7 +197,8 @@ contract Governance is IGovernance, Iupgradable { if(keccak256(_functionHash) == swapABMemberHash) { incentive = 0; } - _categorizeProposal(_proposalId, _categoryId, incentive, _functionHash); + address _msgSenderAddress = _msgSender(); + _categorizeProposal(_proposalId, _categoryId, incentive, _functionHash, _msgSenderAddress); } /** @@ -214,7 +210,11 @@ contract Governance is IGovernance, Iupgradable { uint256 _proposalId, string calldata _solutionHash, bytes calldata _action - ) external onlyProposalOwner(_proposalId) { + ) external { + require( + _msgSender() == allProposalData[_proposalId].owner, + "Not owner" + ); require( allProposalData[_proposalId].propStatus == uint256(ProposalStatus.AwaitingSolution) @@ -239,11 +239,13 @@ contract Governance is IGovernance, Iupgradable { ) external isAllowed(_categoryId) { uint256 proposalId = totalProposals; + address _msgSenderAddress = _msgSender(); _createProposal( _proposalTitle, _proposalSD, _proposalDescHash, - _categoryId + _categoryId, + _msgSenderAddress ); require(_categoryId > 0); @@ -282,7 +284,7 @@ contract Governance is IGovernance, Iupgradable { ) { _updateProposalStatus(_proposalId, uint256(ProposalStatus.Denied)); _transferPLOT( - address(marketRegistry), + address(mcr), allProposalData[_proposalId].commonIncentive ); } else { @@ -290,7 +292,6 @@ contract Governance is IGovernance, Iupgradable { _closeVote(_proposalId, category); } } - /** * @dev Claims reward for member. * @param _memberAddress to claim reward of. @@ -367,8 +368,9 @@ contract Governance is IGovernance, Iupgradable { * @dev Provides option to Advisory board member to reject proposal action execution within actionWaitingTime, if found suspicious */ function rejectAction(uint256 _proposalId) external { + address _msgSenderAddress = _msgSender(); require( - memberRole.checkRole(msg.sender, actionRejectAuthRole) && + memberRole.checkRole(_msgSenderAddress, actionRejectAuthRole) && proposalExecutionTime[_proposalId] > now ); @@ -376,11 +378,11 @@ contract Governance is IGovernance, Iupgradable { proposalActionStatus[_proposalId] == uint256(ActionStatus.Accepted) ); - require(!isActionRejected[_proposalId][msg.sender]); + require(!isActionRejected[_proposalId][_msgSenderAddress]); - isActionRejected[_proposalId][msg.sender] = true; + isActionRejected[_proposalId][_msgSenderAddress] = true; actionRejectedCount[_proposalId]++; - emit ActionRejected(_proposalId, msg.sender); + emit ActionRejected(_proposalId, _msgSenderAddress); if ( actionRejectedCount[_proposalId].mul(100).div( memberRole.numberOfMembers(actionRejectAuthRole) @@ -538,7 +540,7 @@ contract Governance is IGovernance, Iupgradable { * @param val value to set */ function updateUintParameters(bytes8 code, uint256 val) public { - require(ms.isAuthorizedToGovern(msg.sender)); + require(ms.isAuthorizedToGovern(_msgSender())); if (code == "GOVHOLD") { tokenHoldingTime = val * 1 days; } else if (code == "MAXDRFT") { @@ -564,17 +566,19 @@ contract Governance is IGovernance, Iupgradable { * @dev Updates all dependency addresses to latest ones from Master */ function setMasterAddress() public { + address _msgSenderAddress = _msgSender(); OwnedUpgradeabilityProxy proxy = OwnedUpgradeabilityProxy(address(uint160(address(this)))); - require(msg.sender == proxy.proxyOwner(),"Sender is not proxy owner."); + require(_msgSenderAddress == proxy.proxyOwner(),"Sender is not proxy owner."); require(!constructorCheck); _initiateGovernance(); - ms = IMaster(msg.sender); + ms = IMaster(_msgSenderAddress); tokenInstance = IToken(ms.dAppToken()); memberRole = IMemberRoles(ms.getLatestAddress("MR")); proposalCategory = IProposalCategory(ms.getLatestAddress("PC")); tokenController = ITokenController(ms.getLatestAddress("TC")); - marketRegistry = IMarketRegistry(address(uint160(ms.getLatestAddress("PL")))); + allMarkets = IAllMarkets(address(uint160(ms.getLatestAddress("AM")))); + mcr = IMarketCreationRewards(address(uint160(ms.getLatestAddress("MC")))); } /** @@ -588,10 +592,11 @@ contract Governance is IGovernance, Iupgradable { if (category == 0) return true; uint256[] memory mrAllowed; (, , , , mrAllowed, , ) = proposalCategory.category(category); + address _msgSenderAddress = _msgSender(); for (uint256 i = 0; i < mrAllowed.length; i++) { if ( mrAllowed[i] == 0 || - memberRole.checkRole(msg.sender, mrAllowed[i]) + memberRole.checkRole(_msgSenderAddress, mrAllowed[i]) ) return true; } } @@ -604,7 +609,7 @@ contract Governance is IGovernance, Iupgradable { view returns (bool check) { - return memberRole.checkRole(msg.sender, roleIdAllowedToCatgorize); + return memberRole.checkRole(_msgSender(), roleIdAllowedToCatgorize); } /** @@ -701,16 +706,17 @@ contract Governance is IGovernance, Iupgradable { string memory _proposalTitle, string memory _proposalSD, string memory _proposalDescHash, - uint256 _categoryId + uint256 _categoryId, + address _msgSenderAddress ) internal { uint256 _proposalId = totalProposals; - allProposalData[_proposalId].owner = msg.sender; + allProposalData[_proposalId].owner = _msgSenderAddress; allProposalData[_proposalId].dateUpd = now; allProposalSolutions[_proposalId].push(""); totalProposals++; emit Proposal( - msg.sender, + _msgSenderAddress, _proposalId, now, _proposalTitle, @@ -729,7 +735,7 @@ contract Governance is IGovernance, Iupgradable { if(keccak256(_functionHash) == swapABMemberHash) { defaultIncentive = 0; } - _categorizeProposal(_proposalId, _categoryId, defaultIncentive, _functionHash); + _categorizeProposal(_proposalId, _categoryId, defaultIncentive, _functionHash, _msgSenderAddress); } } @@ -743,14 +749,15 @@ contract Governance is IGovernance, Iupgradable { uint256 _proposalId, uint256 _categoryId, uint256 _incentive, - bytes memory _functionHash + bytes memory _functionHash, + address _msgSenderAddress ) internal { require( _categoryId > 0 && _categoryId < proposalCategory.totalCategories(), "Invalid category" ); if(keccak256(_functionHash) == resolveDisputeHash) { - require(msg.sender == address(marketRegistry)); + require(_msgSenderAddress == address(allMarkets)); } allProposalData[_proposalId].category = _categoryId; allProposalData[_proposalId].commonIncentive = _incentive; @@ -759,14 +766,14 @@ contract Governance is IGovernance, Iupgradable { ); if (_incentive > 0) { - marketRegistry.transferAssets( + mcr.transferAssets( address(tokenInstance), address(this), _incentive ); } - emit ProposalCategorized(_proposalId, msg.sender, _categoryId); + emit ProposalCategorized(_proposalId, _msgSenderAddress, _categoryId); } /** @@ -783,7 +790,7 @@ contract Governance is IGovernance, Iupgradable { allProposalSolutions[_proposalId].push(_action); emit Solution( _proposalId, - msg.sender, + _msgSender(), allProposalSolutions[_proposalId].length.sub(1), _solutionHash, now @@ -833,20 +840,20 @@ contract Governance is IGovernance, Iupgradable { allProposalData[_proposalId].dateUpd.add(closingTime) > now, "Closed" ); - + address _msgSenderAddress = _msgSender(); require( - memberProposalVote[msg.sender][_proposalId] == 0, + memberProposalVote[_msgSenderAddress][_proposalId] == 0, "Not allowed" ); - require(memberRole.checkRole(msg.sender, mrSequence), "Not Authorized"); + require(memberRole.checkRole(_msgSenderAddress, mrSequence), "Not Authorized"); uint256 totalVotes = allVotes.length; - allVotesByMember[msg.sender].push(totalVotes); - memberProposalVote[msg.sender][_proposalId] = totalVotes; - tokenController.lockForGovernanceVote(msg.sender, tokenHoldingTime); + allVotesByMember[_msgSenderAddress].push(totalVotes); + memberProposalVote[_msgSenderAddress][_proposalId] = totalVotes; + tokenController.lockForGovernanceVote(_msgSenderAddress, tokenHoldingTime); - emit Vote(msg.sender, _proposalId, totalVotes, now, _solution); + emit Vote(_msgSenderAddress, _proposalId, totalVotes, now, _solution); uint256 numberOfMembers = memberRole.numberOfMembers(mrSequence); _setVoteTally(_proposalId, _solution, mrSequence); @@ -865,10 +872,11 @@ contract Governance is IGovernance, Iupgradable { ) internal { uint256 voters = 1; uint256 voteWeight; - uint256 tokenBalance = tokenController.totalBalanceOf(msg.sender); + address _msgSenderAddress = _msgSender(); + uint256 tokenBalance = tokenController.totalBalanceOf(_msgSenderAddress); uint totalSupply = tokenController.totalSupply(); if (mrSequence != uint(IMemberRoles.Role.AdvisoryBoard) && - memberRole.checkRole(msg.sender, uint(IMemberRoles.Role.AdvisoryBoard)) + memberRole.checkRole(_msgSenderAddress, uint(IMemberRoles.Role.AdvisoryBoard)) ) { proposalVoteTally[_proposalId].abVoteValue[_solution]++; @@ -880,12 +888,12 @@ contract Governance is IGovernance, Iupgradable { } else if ( mrSequence == uint256(IMemberRoles.Role.DisputeResolution) ) { - voteWeight = tokenController.tokensLockedAtTime(msg.sender, "DR", now); + voteWeight = tokenController.tokensLockedAtTime(_msgSenderAddress, "DR", now); } else { voteWeight = 1; } allVotes.push( - ProposalVote(msg.sender, _proposalId, _solution, tokenBalance, now) + ProposalVote(_msgSenderAddress, _proposalId, _solution, tokenBalance, now) ); allProposalData[_proposalId] .totalVoteValue = allProposalData[_proposalId].totalVoteValue.add( @@ -930,8 +938,8 @@ contract Governance is IGovernance, Iupgradable { ) >= categoryQuorumPerc; } else if (roleAuthorized == uint256(IMemberRoles.Role.DisputeResolution)) { - (address marketAddress, ) = abi.decode(allProposalSolutions[_proposalId][1], (address, uint256)); - uint256 totalStakeValueInPlot = IMarket(marketAddress).getTotalStakedValueInPLOT(); + (uint256 marketId, ) = abi.decode(allProposalSolutions[_proposalId][1], (uint256, uint256)); + uint256 totalStakeValueInPlot = allMarkets.getTotalStakedWorthInPLOT(marketId); if(allProposalData[_proposalId].totalVoteValue > 0) { check = (allProposalData[_proposalId].totalVoteValue) >= @@ -1003,12 +1011,24 @@ contract Governance is IGovernance, Iupgradable { } else if (contractName != "EX") { actionAddress = ms.getLatestAddress(contractName); } - (bool actionStatus, ) = actionAddress.call( - abi.encodePacked( - _functionHash, - allProposalSolutions[_proposalId][1] - ) - ); + bool actionStatus; + if(contractName == "GV") { + (actionStatus, ) = actionAddress.call( + abi.encodePacked( + _functionHash, + allProposalSolutions[_proposalId][1], + address(this) + ) + ); + } + else { + (actionStatus, ) = actionAddress.call( + abi.encodePacked( + _functionHash, + allProposalSolutions[_proposalId][1] + ) + ); + } if (actionStatus) { emit ActionSuccess(_proposalId); } else { @@ -1089,13 +1109,13 @@ contract Governance is IGovernance, Iupgradable { } if(allProposalData[_proposalId].propStatus > uint256(ProposalStatus.Accepted)) { if(keccak256(_functionHash) == resolveDisputeHash) { - marketRegistry.burnDisputedProposalTokens(_proposalId); + allMarkets.burnDisputedProposalTokens(_proposalId); } } if (proposalVoteTally[_proposalId].voters == 0 && allProposalData[_proposalId].commonIncentive > 0) { _transferPLOT( - address(marketRegistry), + address(mcr), allProposalData[_proposalId].commonIncentive ); } @@ -1117,6 +1137,7 @@ contract Governance is IGovernance, Iupgradable { allVotes.push(ProposalVote(address(0), 0, 0, 0, 0)); totalProposals = 1; tokenHoldingTime = 1 * 3 days; + maxDraftTime = 14 days; constructorCheck = true; roleIdAllowedToCatgorize = uint256(IMemberRoles.Role.AdvisoryBoard); actionWaitingTime = 1 days; @@ -1125,6 +1146,7 @@ contract Governance is IGovernance, Iupgradable { maxVoteWeigthPer = 5; advisoryBoardMajority = 60; drQuorumMulitplier = 5; + _initializeEIP712("GV"); } } diff --git a/contracts/Market.sol b/contracts/Market.sol deleted file mode 100644 index 1a646f79b..000000000 --- a/contracts/Market.sol +++ /dev/null @@ -1,594 +0,0 @@ -/* 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 Market { - 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; - } - uint[] memory totalReward = 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); - } - } - 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, 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/MarketCreationRewards.sol b/contracts/MarketCreationRewards.sol new file mode 100644 index 000000000..9fe4635c7 --- /dev/null +++ b/contracts/MarketCreationRewards.sol @@ -0,0 +1,246 @@ +pragma solidity 0.5.7; + +import "./external/proxy/OwnedUpgradeabilityProxy.sol"; +import "./external/openzeppelin-solidity/math/SafeMath.sol"; +import "./external/openzeppelin-solidity/math/Math.sol"; +import "./external/govblocks-protocol/Governed.sol"; +// import "./interfaces/ITokenController.sol"; +import "./interfaces/IToken.sol"; +import "./interfaces/IAllMarkets.sol"; +import "./external/NativeMetaTransaction.sol"; + +contract MarketCreationRewards is Governed, NativeMetaTransaction { + + using SafeMath for *; + + event MarketCreatorRewardPoolShare(address indexed createdBy, uint256 indexed marketIndex, uint256 tokenIncentive); + event MarketCreationReward(address indexed createdBy, uint256 marketIndex); + event ClaimedMarketCreationReward(address indexed user, uint rewardPoolShare, address predictionToken); + + modifier onlyInternal() { + IMaster(masterAddress).isInternal(msg.sender); + _; + } + + struct MarketCreationRewardData { + uint tokenIncentive; + // uint64 tokenDeposited; + // uint16 rewardPoolSharePerc; + address createdBy; + } + + struct MarketCreationRewardUserData { + uint128 lastClaimedIndex; + uint256 rewardEarned; + uint64[] marketsCreated; + } + + // uint16 internal maxRewardPoolPercForMC; + // uint16 internal minRewardPoolPercForMC; + address internal plotToken; + address internal predictionToken; + // uint256 internal tokenStakeForRewardPoolShare; + // uint256 internal rewardPoolShareThreshold; + uint internal predictionDecimalMultiplier; + // ITokenController internal tokenController; + IAllMarkets internal allMarkets; + mapping(uint256 => MarketCreationRewardData) internal marketCreationRewardData; //Of market + mapping(address => MarketCreationRewardUserData) internal marketCreationRewardUserData; //Of user + + /** + * @dev Changes the master address and update it's instance + */ + function setMasterAddress() public { + OwnedUpgradeabilityProxy proxy = OwnedUpgradeabilityProxy(address(uint160(address(this)))); + require(msg.sender == proxy.proxyOwner(),"not owner."); + IMaster ms = IMaster(msg.sender); + masterAddress = msg.sender; + plotToken = ms.dAppToken(); + predictionToken = ms.dAppToken(); + // tokenController = ITokenController(ms.getLatestAddress("TC")); + allMarkets = IAllMarkets(ms.getLatestAddress("AM")); + _initialise(); + } + + /** + * @dev Function to set inital parameters of contract + */ + function _initialise() internal { + // maxRewardPoolPercForMC = 500; // Raised by 2 decimals + // minRewardPoolPercForMC = 50; // Raised by 2 decimals + // tokenStakeForRewardPoolShare = 25000 ether; + // rewardPoolShareThreshold = 400 ether; //need to change value (in prediction token) + predictionDecimalMultiplier = 10; + _initializeEIP712("MC"); + } + + // /** + // * @dev function to update integer parameters + // */ + // function updateUintParameters(bytes8 code, uint256 value) external onlyAuthorizedToGovern { + // if(code == "MAXRPSP") { // Max Reward Pool percent for market creator + // maxRewardPoolPercForMC = uint16(value); + // } else if(code == "MINRPSP") { // Min Reward Pool percent for market creator + // minRewardPoolPercForMC = uint16(value); + // } else if(code == "PSFRPS") { // Reward Pool percent for market creator + // tokenStakeForRewardPoolShare = value; + // } else if(code == "RPSTH") { // Reward Pool percent for market creator + // rewardPoolShareThreshold = value; + // } + // } + + // /** + // * @dev function to get integer parameters + // */ + // function getUintParameters(bytes8 code) external view returns(bytes8 codeVal, uint256 value) { + // codeVal = code; + // if(code == "MAXRPSP") { // Max Reward Pool percent for market creator + // value = maxRewardPoolPercForMC; + // } else if(code == "MINRPSP") { // Min Reward Pool percent for market creator + // value = minRewardPoolPercForMC; + // } else if(code == "PSFRPS") { // Reward Pool percent for market creator + // value = tokenStakeForRewardPoolShare; + // } else if(code == "RPSTH") { // Reward Pool percent for market creator + // value = rewardPoolShareThreshold; + // } + // } + + // /** + // * @dev internal function to calculate market reward pool share percent to be rewarded to market creator + // */ + // function _checkIfCreatorStaked(address _createdBy, uint64 _marketId) internal { + // uint256 tokensLocked = ITokenController(tokenController).tokensLockedAtTime(_createdBy, "SM", now); + // marketCreationRewardData[_marketId].createdBy = _createdBy; + // //Intentionally performed mul operation after div, to get absolute value instead of decimals + // marketCreationRewardData[_marketId].rewardPoolSharePerc + // = uint16(Math.min( + // maxRewardPoolPercForMC, + // minRewardPoolPercForMC + tokensLocked.div(tokenStakeForRewardPoolShare).mul(minRewardPoolPercForMC) + // )); + // } + + /** + * @dev function to calculate user incentive for market creation + * @param _createdBy Address of market creator + * @param _marketId Index of market + */ + function calculateMarketCreationIncentive(address _createdBy, uint64 _marketId) external onlyInternal { + marketCreationRewardData[_marketId].createdBy = _createdBy; + // _checkIfCreatorStaked(_createdBy, _marketId); + marketCreationRewardUserData[_createdBy].marketsCreated.push(_marketId); + emit MarketCreationReward(_createdBy, _marketId); + } + + /** + * @dev Function to deposit market reward pool share funds for market creator + * @param _marketId Index of market + * @param _tokenShare prediction token fee share earned by + */ + function depositMarketCreationReward(uint256 _marketId, uint256 _tokenShare) external onlyInternal { + marketCreationRewardUserData[marketCreationRewardData[_marketId].createdBy].rewardEarned = _tokenShare; + // marketCreationRewardData[_marketId].tokenDeposited = _tokenDeposited; + emit MarketCreatorRewardPoolShare(marketCreationRewardData[_marketId].createdBy, _marketId, _tokenShare); + } + + /** + * @dev function to reward user for initiating market creation calls as per the new incetive calculations + */ + function claimCreationReward(uint256 _maxRecords) external { + address payable _msgSender = _msgSender(); + // uint256 rewardPoolShare = _getRewardPoolIncentives(_maxRecords); + uint256 rewardPoolShare = marketCreationRewardUserData[_msgSender].rewardEarned; + require(rewardPoolShare > 0, "No pending"); + _transferAsset(address(predictionToken), _msgSender, rewardPoolShare); + emit ClaimedMarketCreationReward(_msgSender, rewardPoolShare, predictionToken); + } + + /** + * @dev Transfer `_amount` number of market registry assets contract to `_to` address + */ + function transferAssets(address _asset, address payable _to, uint _amount) external onlyAuthorizedToGovern { + _transferAsset(_asset, _to, _amount); + } + + // /** + // * @dev internal function to calculate market reward pool share incentives for market creator + // */ + // function _getRewardPoolIncentives(uint256 _maxRecords) internal returns(uint256 tokenIncentive) { + // MarketCreationRewardUserData storage rewardData = marketCreationRewardUserData[_msgSender()]; + // uint256 len = rewardData.marketsCreated.length; + // uint256 lastClaimed = len; + // uint256 count; + // uint128 i; + // for(i = rewardData.lastClaimedIndex;i < len && count < _maxRecords; i++) { + // MarketCreationRewardData storage marketData = marketCreationRewardData[rewardData.marketsCreated[i]]; + // if(allMarkets.marketStatus(rewardData.marketsCreated[i]) == IAllMarkets.PredictionStatus.Settled) { + // tokenIncentive = tokenIncentive.add(marketData.tokenIncentive); + // delete marketData.tokenIncentive; + // count++; + // } else { + // if(lastClaimed == len) { + // lastClaimed = i; + // } + // } + // } + // if(lastClaimed == len) { + // lastClaimed = i; + // } + // rewardData.lastClaimedIndex = uint128(lastClaimed); + // } + + /** + * @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 tokenIncentive Incentives given for creating market as per the gas consumed + * @return pendingTokenReward prediction token Reward pool share of markets created by user + */ + function getPendingMarketCreationRewards(address _user) external view returns(uint256 tokenIncentive){ + tokenIncentive = marketCreationRewardUserData[_user].rewardEarned; + // pendingTokenReward = _getPendingRewardPoolIncentives(_user); + } + + // /** + // * @dev Get market reward pool share percent to be rewarded to market creator + // */ + // function getMarketCreatorRPoolShareParams(uint256 _market, uint256 _tokenStaked) external view returns(uint16, bool) { + // return (marketCreationRewardData[_market].rewardPoolSharePerc, _checkIfThresholdReachedForRPS(_tokenStaked)); + // } + + // * + // * @dev Check if threshold reached for reward pool share percent for market creator. + // * Calculate total leveraged amount staked in market value in prediction token + // * @param _tokenStaked Total assets staked on market + + // function _checkIfThresholdReachedForRPS(uint256 _tokenStaked) internal view returns(bool) { + // return (_tokenStaked.mul(10**predictionDecimalMultiplier) > rewardPoolShareThreshold); + // } + + // /** + // * @dev internal function to calculate market reward pool share incentives for market creator + // */ + // function _getPendingRewardPoolIncentives(address _user) internal view returns(uint256 tokenIncentive) { + // 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]]; + // if(marketData.tokenIncentive > 0) { + // if(allMarkets.marketStatus(rewardData.marketsCreated[i]) == IAllMarkets.PredictionStatus.Settled) { + // tokenIncentive = tokenIncentive.add(marketData.tokenIncentive); + // } + // } + // } + // } + + /** + * @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) { + require(IToken(_asset).transfer(_recipient, _amount)); + } + } + +} diff --git a/contracts/MarketRegistry.sol b/contracts/MarketRegistry.sol deleted file mode 100644 index e6c36f80d..000000000 --- a/contracts/MarketRegistry.sol +++ /dev/null @@ -1,593 +0,0 @@ -/* 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/govblocks-protocol/interfaces/IGovernance.sol"; -import "./external/govblocks-protocol/Governed.sol"; -import "./external/proxy/OwnedUpgradeabilityProxy.sol"; -import "./interfaces/IToken.sol"; -import "./interfaces/IMarket.sol"; -import "./interfaces/Iupgradable.sol"; -import "./interfaces/IMarketUtility.sol"; - -contract MarketRegistry is Governed, Iupgradable { - - using SafeMath for *; - - enum MarketType { - HourlyMarket, - DailyMarket, - WeeklyMarket - } - - struct MarketTypeData { - uint64 predictionTime; - uint64 optionRangePerc; - } - - struct MarketCurrency { - address marketImplementation; - uint8 decimals; - } - - struct MarketCreationData { - uint64 initialStartTime; - address marketAddress; - address penultimateMarket; - } - - struct DisputeStake { - uint64 proposalId; - address staker; - uint256 stakeAmount; - uint256 ethDeposited; - uint256 tokenDeposited; - } - - struct MarketData { - bool isMarket; - DisputeStake disputeStakes; - } - - struct UserData { - uint256 lastClaimedIndex; - uint256 marketsCreated; - uint256 totalEthStaked; - uint256 totalPlotStaked; - address[] marketsParticipated; - mapping(address => bool) marketsParticipatedFlag; - } - - uint internal marketCreationIncentive; - - mapping(address => MarketData) marketData; - mapping(address => UserData) userData; - mapping(uint256 => mapping(uint256 => MarketCreationData)) public marketCreationData; - mapping(uint64 => address) disputeProposalId; - - address constant ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE; - address internal marketInitiater; - address public tokenController; - - MarketCurrency[] marketCurrencies; - MarketTypeData[] marketTypes; - - bool public marketCreationPaused; - - IToken public plotToken; - IMarketUtility public marketUtility; - IGovernance internal governance; - IMaster ms; - - - 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); - event MarketResult(address indexed marketAdd, uint256[] totalReward, uint256 winningOption, uint256 closeValue, uint256 roundId); - event Claimed(address indexed marketAdd, address indexed user, uint256[] reward, address[] _predictionAssets, uint256 incentive, address incentiveToken); - event MarketTypes(uint256 indexed index, uint64 predictionTime, uint64 optionRangePerc); - 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); - - /** - * @dev Checks if given addres is valid market address. - */ - function isMarket(address _address) public view returns(bool) { - return marketData[_address].isMarket; - } - - function isWhitelistedSponsor(address _address) public view returns(bool) { - return ms.whitelistedSponsor(_address); - } - - /** - * @dev Initialize the PlotX MarketRegistry. - * @param _defaultAddress Address authorized to start initial markets - * @param _marketUtility The address of market config. - * @param _plotToken The instance of PlotX token. - */ - function initiate(address _defaultAddress, address _marketUtility, address _plotToken, address payable[] memory _configParams) public { - require(address(ms) == msg.sender); - marketCreationIncentive = 50 ether; - plotToken = IToken(_plotToken); - address tcAddress = ms.getLatestAddress("TC"); - tokenController = tcAddress; - marketUtility = IMarketUtility(_generateProxy(_marketUtility)); - marketUtility.initialize(_configParams, _defaultAddress); - marketInitiater = _defaultAddress; - } - - /** - * @dev Start the initial market. - */ - function addInitialMarketTypesAndStart(uint64 _marketStartTime, address _ethMarketImplementation, address _btcMarketImplementation) external { - require(marketInitiater == msg.sender); - require(marketTypes.length == 0); - _addNewMarketCurrency(_ethMarketImplementation); - _addNewMarketCurrency(_btcMarketImplementation); - _addMarket(1 hours, 50); - _addMarket(24 hours, 200); - _addMarket(7 days, 500); - - for(uint256 i = 0;i < marketTypes.length; i++) { - marketCreationData[i][0].initialStartTime = _marketStartTime; - marketCreationData[i][1].initialStartTime = _marketStartTime; - createMarket(i, 0); - createMarket(i, 1); - } - } - - /** - * @dev Add new market type. - * @param _predictionTime The time duration of market. - * @param _marketStartTime The time at which market will create. - * @param _optionRangePerc Option range percent of neutral min, max options (raised by 2 decimals) - */ - function addNewMarketType(uint64 _predictionTime, uint64 _marketStartTime, uint64 _optionRangePerc) external onlyAuthorizedToGovern { - require(_marketStartTime > now); - uint256 _marketType = marketTypes.length; - _addMarket(_predictionTime, _optionRangePerc); - for(uint256 j = 0;j < marketCurrencies.length; j++) { - marketCreationData[_marketType][j].initialStartTime = _marketStartTime; - createMarket(_marketType, j); - } - } - - /** - * @dev Internal function to add market type - * @param _predictionTime The time duration of market. - * @param _optionRangePerc Option range percent of neutral min, max options (raised by 2 decimals) - */ - function _addMarket(uint64 _predictionTime, uint64 _optionRangePerc) internal { - uint256 _marketType = marketTypes.length; - marketTypes.push(MarketTypeData(_predictionTime, _optionRangePerc)); - emit MarketTypes(_marketType, _predictionTime, _optionRangePerc); - } - - /** - * @dev Add new market currency. - */ - function addNewMarketCurrency(address _marketImplementation, uint64 _marketStartTime) external onlyAuthorizedToGovern { - uint256 _marketCurrencyIndex = marketCurrencies.length; - _addNewMarketCurrency(_marketImplementation); - for(uint256 j = 0;j < marketTypes.length; j++) { - marketCreationData[j][_marketCurrencyIndex].initialStartTime = _marketStartTime; - createMarket(j, _marketCurrencyIndex); - } - } - - function _addNewMarketCurrency(address _marketImplementation) internal { - uint256 _marketCurrencyIndex = marketCurrencies.length; - (, bytes32 _currencyName, address _priceFeed) = IMarket(_marketImplementation).getMarketFeedData(); - uint8 _decimals = marketUtility.getPriceFeedDecimals(_priceFeed); - marketCurrencies.push(MarketCurrency(_marketImplementation, _decimals)); - emit MarketCurrencies(_marketCurrencyIndex, _marketImplementation, _priceFeed, _currencyName); - } - - /** - * @dev Update the implementations of the market. - */ - function updateMarketImplementations(uint256[] calldata _currencyIndexes, address[] calldata _marketImplementations) external onlyAuthorizedToGovern { - require(_currencyIndexes.length == _marketImplementations.length); - for(uint256 i = 0;i< _currencyIndexes.length; i++) { - (, , address _priceFeed) = IMarket(_marketImplementations[i]).getMarketFeedData(); - uint8 _decimals = marketUtility.getPriceFeedDecimals(_priceFeed); - marketCurrencies[_currencyIndexes[i]] = MarketCurrency(_marketImplementations[i], _decimals); - } - } - - /** - * @dev Upgrade the implementations of the contract. - * @param _proxyAddress the proxy address. - * @param _newImplementation Address of new implementation contract - */ - function upgradeContractImplementation(address payable _proxyAddress, address _newImplementation) - external onlyAuthorizedToGovern - { - require(_newImplementation != address(0)); - OwnedUpgradeabilityProxy tempInstance - = OwnedUpgradeabilityProxy(_proxyAddress); - tempInstance.upgradeTo(_newImplementation); - } - - /** - * @dev Changes the master address and update it's instance - */ - function setMasterAddress() public { - OwnedUpgradeabilityProxy proxy = OwnedUpgradeabilityProxy(address(uint160(address(this)))); - require(msg.sender == proxy.proxyOwner(),"Sender is not proxy owner."); - ms = IMaster(msg.sender); - masterAddress = msg.sender; - governance = IGovernance(ms.getLatestAddress("GV")); - } - - /** - * @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, uint64 _minValue, uint64 _maxValue, uint64 _marketStartTime, bytes32 _currencyName) internal { - require(!marketCreationPaused); - MarketTypeData memory _marketTypeData = marketTypes[_marketType]; - address payable _market = _generateProxy(marketCurrencies[_marketCurrencyIndex].marketImplementation); - marketData[_market].isMarket = true; - IMarket(_market).initiate(_marketStartTime, _marketTypeData.predictionTime, _minValue, _maxValue); - emit MarketQuestion(_market, _currencyName, _marketType, _marketStartTime); - (marketCreationData[_marketType][_marketCurrencyIndex].penultimateMarket, marketCreationData[_marketType][_marketCurrencyIndex].marketAddress) = - (marketCreationData[_marketType][_marketCurrencyIndex].marketAddress, _market); - } - - /** - * @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{ - 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++; - } - - /** - * @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); - } - - function calculateStartTimeForMarket(uint256 _marketType, uint256 _marketCurrencyIndex) public view returns(uint64 _marketStartTime) { - address previousMarket = marketCreationData[_marketType][_marketCurrencyIndex].marketAddress; - if(previousMarket != address(0)) { - (_marketStartTime, , , ) = IMarket(previousMarket).marketData(); - } else { - _marketStartTime = marketCreationData[_marketType][_marketCurrencyIndex].initialStartTime; - } - uint predictionTime = marketTypes[_marketType].predictionTime; - if(now > _marketStartTime.add(predictionTime)) { - uint noOfMarketsSkipped = ((now).sub(_marketStartTime)).div(predictionTime); - _marketStartTime = uint64(_marketStartTime.add(noOfMarketsSkipped.mul(predictionTime))); - } - } - - /** - * @dev Updates Flag to pause creation of market. - */ - function pauseMarketCreation() external onlyAuthorizedToGovern { - require(!marketCreationPaused); - marketCreationPaused = true; - } - - /** - * @dev Updates Flag to resume creation of market. - */ - function resumeMarketCreation() external onlyAuthorizedToGovern { - require(marketCreationPaused); - marketCreationPaused = false; - } - - /** - * @dev Create proposal if user wants to raise the dispute. - * @param proposalTitle The title of proposal created by user. - * @param description The description of dispute. - * @param solutionHash The ipfs solution hash. - * @param action The encoded action for solution. - * @param _stakeForDispute The token staked to raise the diospute. - * @param _user The address who raises the dispute. - */ - function createGovernanceProposal(string memory proposalTitle, string memory description, string memory solutionHash, bytes memory action, uint256 _stakeForDispute, address _user, uint256 _ethSentToPool, uint256 _tokenSentToPool, uint256 _proposedValue) public { - require(isMarket(msg.sender)); - uint64 proposalId = uint64(governance.getProposalLength()); - marketData[msg.sender].disputeStakes = DisputeStake(proposalId, _user, _stakeForDispute, _ethSentToPool, _tokenSentToPool); - disputeProposalId[proposalId] = msg.sender; - governance.createProposalwithSolution(proposalTitle, proposalTitle, description, 10, solutionHash, action); - emit DisputeRaised(msg.sender, _user, proposalId, _proposedValue); - } - - /** - * @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); - _transferAsset(plotTokenAddress, _marketAddress, plotDepositedInPool); - IMarket(_marketAddress).resolveDispute.value(ethDepositedInPool)(true, _result); - emit DisputeResolved(_marketAddress, true); - _transferAsset(plotTokenAddress, staker, stakedAmount); - } - - /** - * @dev Burns the tokens of member who raised the dispute, if dispute is rejected. - * @param _proposalId Id of dispute resolution proposal - */ - function burnDisputedProposalTokens(uint _proposalId) external onlyAuthorizedToGovern { - address disputedMarket = disputeProposalId[uint64(_proposalId)]; - IMarket(disputedMarket).resolveDispute(false, 0); - emit DisputeResolved(disputedMarket, false); - uint _stakedAmount = marketData[disputedMarket].disputeStakes.stakeAmount; - plotToken.burn(_stakedAmount); - } - - /** - * @dev Claim the pending return of the market. - * @param maxRecords Maximum number of records to claim reward for - */ - function claimPendingReturn(uint256 maxRecords) external { - uint256 i; - uint len = userData[msg.sender].marketsParticipated.length; - uint lastClaimed = len; - uint count; - for(i = userData[msg.sender].lastClaimedIndex; i < len && count < maxRecords; i++) { - if(IMarket(userData[msg.sender].marketsParticipated[i]).claimReturn(msg.sender) > 0) { - count++; - } else { - if(lastClaimed == len) { - lastClaimed = i; - } - } - } - if(lastClaimed == len) { - lastClaimed = i; - } - userData[msg.sender].lastClaimedIndex = lastClaimed; - } - - function () external payable { - } - - - /** - * @dev Transfer `_amount` number of market registry assets contract to `_to` address - */ - function transferAssets(address _asset, address payable _to, uint _amount) external onlyAuthorizedToGovern { - _transferAsset(_asset, _to, _amount); - } - - /** - * @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)); - } - } - } - - function updateUintParameters(bytes8 code, uint256 value) external onlyAuthorizedToGovern { - if(code == "MCRINC") { // Incentive to be distributed to user for market creation - marketCreationIncentive = value; - } else { - marketUtility.updateUintParameters(code, value); - } - } - - function updateConfigAddressParameters(bytes8 code, address payable value) external onlyAuthorizedToGovern { - marketUtility.updateAddressParameters(code, value); - } - - /** - * @dev to generater proxy - * @param _contractAddress of the proxy - */ - function _generateProxy(address _contractAddress) internal returns(address payable) { - OwnedUpgradeabilityProxy tempInstance = new OwnedUpgradeabilityProxy(_contractAddress); - return address(tempInstance); - } - - /** - * @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 winningOption, uint256 closeValue, uint _roundId) external { - require(isMarket(msg.sender)); - emit MarketResult(msg.sender, _totalReward, winningOption, closeValue, _roundId); - } - - /** - * @dev Emits the PlacePrediction event and sets the user data. - * @param _user The address who placed prediction. - * @param _value The amount of ether user staked. - * @param _predictionPoints The positions user will get. - * @param _predictionAsset The prediction assets user will get. - * @param _prediction The option range on which user placed prediction. - * @param _leverage The leverage selected by user at the time of place prediction. - */ - function setUserGlobalPredictionData(address _user,uint256 _value, uint256 _predictionPoints, address _predictionAsset, uint256 _prediction, uint256 _leverage) external { - require(isMarket(msg.sender)); - if(_predictionAsset == ETH_ADDRESS) { - userData[_user].totalEthStaked = userData[_user].totalEthStaked.add(_value); - } else { - userData[_user].totalPlotStaked = userData[_user].totalPlotStaked.add(_value); - } - if(!userData[_user].marketsParticipatedFlag[msg.sender]) { - userData[_user].marketsParticipated.push(msg.sender); - userData[_user].marketsParticipatedFlag[msg.sender] = true; - } - emit PlacePrediction(_user, _value, _predictionPoints, _predictionAsset, _prediction, msg.sender,_leverage); - } - - /** - * @dev Emits the claimed event. - * @param _user The address who claim their reward. - * @param _reward The reward which is claimed by user. - * @param predictionAssets The prediction assets of user. - * @param incentives The incentives of user. - * @param incentiveToken The incentive tokens of user. - */ - function callClaimedEvent(address _user ,uint[] calldata _reward, address[] calldata predictionAssets, uint incentives, address incentiveToken) external { - require(isMarket(msg.sender)); - emit Claimed(msg.sender, _user, _reward, predictionAssets, incentives, incentiveToken); - } - - /** - * @dev Get uint config parameters - */ - function getUintParameters(bytes8 code) external view returns(bytes8 codeVal, uint256 value) { - if(code == "MCRINC") { - codeVal = code; - value = marketCreationIncentive; - } - } - - /** - * @dev Gets the market details of the specified address. - * @param _marketAdd The market address to query the details of market. - * @return _feedsource 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 _predictionType uint representing the type of market. - * @return _expireTime uint representing the expire time of the market. - * @return _predictionStatus uint representing the status of the market. - */ - function getMarketDetails(address _marketAdd)public view returns - (bytes32 _feedsource,uint256[] memory minvalue,uint256[] memory maxvalue, - uint256[] memory optionprice,uint256[] memory _ethStaked, uint256[] memory _plotStaked,uint256 _predictionType,uint256 _expireTime, uint256 _predictionStatus){ - return IMarket(_marketAdd).getData(); - } - - /** - * @dev Get total assets staked by user in PlotX platform - * @return _plotStaked Total PLOT staked by user - * @return _ethStaked Total ETH staked by user - */ - function getTotalAssetStakedByUser(address _user) external view returns(uint256 _plotStaked, uint256 _ethStaked) { - return (userData[_user].totalPlotStaked, userData[_user].totalEthStaked); - } - - /** - * @dev Gets the market details of the specified user address. - * @param user The address to query the details of market. - * @param fromIndex The index to query the details from. - * @param toIndex The index to query the details to - * @return _market address[] memory representing the address of the market. - * @return _winnigOption uint256[] memory representing the winning option range of the market. - */ - function getMarketDetailsUser(address user, uint256 fromIndex, uint256 toIndex) external view returns - (address[] memory _market, uint256[] memory _winnigOption){ - uint256 totalMarketParticipated = userData[user].marketsParticipated.length; - if(totalMarketParticipated > 0 && fromIndex < totalMarketParticipated) { - uint256 _toIndex = toIndex; - if(_toIndex >= totalMarketParticipated) { - _toIndex = totalMarketParticipated - 1; - } - _market = new address[](_toIndex.sub(fromIndex).add(1)); - _winnigOption = new uint256[](_toIndex.sub(fromIndex).add(1)); - for(uint256 i = fromIndex; i <= _toIndex; i++) { - _market[i] = userData[user].marketsParticipated[i]; - (_winnigOption[i], ) = IMarket(_market[i]).marketSettleData(); - } - } - } - - /** - * @dev Gets the addresses of open markets. - * @return _openMarkets address[] memory representing the open market addresses. - * @return _marketTypes uint256[] memory representing the open market types. - */ - function getOpenMarkets() external view returns(address[] memory _openMarkets, uint256[] memory _marketTypes, bytes32[] memory _marketCurrencies) { - uint256 count = 0; - uint256 marketTypeLength = marketTypes.length; - uint256 marketCurrencyLength = marketCurrencies.length; - _openMarkets = new address[]((marketTypeLength).mul(marketCurrencyLength)); - _marketTypes = new uint256[]((marketTypeLength).mul(marketCurrencyLength)); - _marketCurrencies = new bytes32[]((marketTypeLength).mul(marketCurrencyLength)); - for(uint256 i = 0; i< marketTypeLength; i++) { - for(uint256 j = 0; j< marketCurrencyLength; j++) { - _openMarkets[count] = marketCreationData[i][j].marketAddress; - _marketTypes[count] = i; - _marketCurrencies[count] = IMarket(marketCurrencies[j].marketImplementation).marketCurrency(); - count++; - } - } - } - - function ceil(uint256 a, uint256 m) internal pure returns (uint256) { - return ((a + m - 1) / m) * m; - } - - // /** - // * @dev Calculates the user pending return amount. - // * @param _user The address to query the pending return amount of. - // * @return pendingReturn uint256 representing the pending return amount of user. - // * @return incentive uint256 representing the incentive. - // */ - // function calculateUserPendingReturn(address _user) external view returns(uint[] memory returnAmount, address[] memory _predictionAssets, uint[] memory incentive, address[] memory _incentiveTokens) { - // uint256 _return; - // uint256 _incentive; - // for(uint256 i = lastClaimedIndex[_user]; i < marketsParticipated[_user].length; i++) { - // // pendingReturn = pendingReturn.add(marketsParticipated[_user][i].call(abi.encodeWithSignature("getPendingReturn(uint256)", _user))); - // (_return, _incentive) = IMarket(marketsParticipated[_user][i]).getPendingReturn(_user); - // pendingReturn = pendingReturn.add(_return); - // incentive = incentive.add(_incentive); - // } - // } - -} diff --git a/contracts/MarketUtility.sol b/contracts/MarketUtility.sol index 46aa13d60..8ebbed511 100644 --- a/contracts/MarketUtility.sol +++ b/contracts/MarketUtility.sol @@ -15,62 +15,66 @@ pragma solidity 0.5.7; -import "./external/uniswap/solidity-interface.sol"; -import "./external/uniswap/FixedPoint.sol"; -import "./external/uniswap/oracleLibrary.sol"; import "./external/openzeppelin-solidity/math/SafeMath.sol"; import "./external/proxy/OwnedUpgradeabilityProxy.sol"; +import "./external/govblocks-protocol/Governed.sol"; import "./interfaces/ITokenController.sol"; import "./interfaces/IMarketRegistry.sol"; import "./interfaces/IChainLinkOracle.sol"; import "./interfaces/IToken.sol"; +import "./interfaces/IAllMarkets.sol"; -contract MarketUtility { +contract MarketUtility is Governed { using SafeMath for uint256; - using FixedPoint for *; + using SafeMath64 for uint64; - address constant ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE; uint256 constant updatePeriod = 1 hours; - uint256 internal STAKE_WEIGHTAGE; - uint256 internal STAKE_WEIGHTAGE_MIN_AMOUNT; - uint256 internal minTimeElapsedDivisor; uint256 internal minPredictionAmount; uint256 internal maxPredictionAmount; uint256 internal positionDecimals; - uint256 internal minStakeForMultiplier; - uint256 internal riskPercentage; uint256 internal tokenStakeForDispute; - address internal plotToken; - address internal plotETHpair; - address internal weth; - address internal initiater; - address public authorizedAddress; bool public initialized; + // Minimum prediction amount in market needed to kick-in staking factor in option pricing calculation + uint256 public stakingFactorMinStake; + // Weightage given to staking factor in option pricing + uint32 public stakingFactorWeightage; + // Weightage given to current price in option pricing + uint32 public currentPriceWeightage; - struct UniswapPriceData { - FixedPoint.uq112x112 price0Average; - uint256 price0CumulativeLast; - FixedPoint.uq112x112 price1Average; - uint256 price1CumulativeLast; - uint32 blockTimestampLast; - bool initialized; - } - mapping(address => UniswapPriceData) internal uniswapPairData; - IUniswapV2Factory uniswapFactory; + mapping(address => uint256) public conversionRate; + mapping(address => uint256) public userLevel; + mapping(uint256 => uint256) public levelMultiplier; + mapping (address => bool) internal authorizedAddresses; + // Mapping to store latest price of currency type if it's feed address is null. + mapping(bytes32 => uint) public marketTypeFeedPrice; + ITokenController internal tokenController; + IAllMarkets internal allMarkets; modifier onlyAuthorized() { - require(msg.sender == authorizedAddress, "Not authorized"); + require(authorizedAddresses[msg.sender], "Not authorized"); _; } + /** + * @dev Changes the master address and update it's instance + */ + function setMasterAddress() public { + OwnedUpgradeabilityProxy proxy = OwnedUpgradeabilityProxy(address(uint160(address(this)))); + require(msg.sender == proxy.proxyOwner(),"not owner."); + IMaster ms = IMaster(msg.sender); + tokenController = ITokenController(ms.getLatestAddress("TC")); + allMarkets = IAllMarkets(ms.getLatestAddress("AM")); + masterAddress = msg.sender; + } + /** * @dev Initiates the config contact with initial values **/ - function initialize(address payable[] memory _addressParams, address _initiater) public { + function initialize(address _initiater) public { OwnedUpgradeabilityProxy proxy = OwnedUpgradeabilityProxy( address(uint160(address(this))) ); @@ -78,48 +82,48 @@ contract MarketUtility { require(!initialized, "Already initialized"); initialized = true; _setInitialParameters(); - authorizedAddress = msg.sender; - tokenController = ITokenController(IMarketRegistry(msg.sender).tokenController()); - plotToken = _addressParams[1]; - initiater = _initiater; - weth = IUniswapV2Router02(_addressParams[0]).WETH(); - uniswapFactory = IUniswapV2Factory(_addressParams[2]); + authorizedAddresses[_initiater] = true; + } + + /** + * @dev Function to set authorized address + **/ + function addAuthorizedAddress(address _address) external onlyAuthorized { + authorizedAddresses[_address] = true; + } + + /** + * @dev Function to check if given `_address` is authorized address + **/ + function isAuthorized(address _address) external view returns(bool) { + return authorizedAddresses[_address]; } /** * @dev Internal function to set initial value **/ function _setInitialParameters() internal { - STAKE_WEIGHTAGE = 40; // - STAKE_WEIGHTAGE_MIN_AMOUNT = 20 ether; - minTimeElapsedDivisor = 6; - minPredictionAmount = 1e15; - maxPredictionAmount = 28 ether; + minPredictionAmount = 10 ether;// need to change the value according to prediction token + maxPredictionAmount = 100000 ether; // need to change the value according to prediction token positionDecimals = 1e2; - minStakeForMultiplier = 5e17; - riskPercentage = 20; tokenStakeForDispute = 500 ether; + stakingFactorMinStake = uint(20000).mul(10**8); + stakingFactorWeightage = 40; + currentPriceWeightage = 60; } /** * @dev Check if user gets any multiplier on his positions - * @param _asset The assets uses by user during prediction. - * @param _predictionStake The amount staked by user at the time of prediction. + * @param _user User address * @param predictionPoints The actual positions user got during prediction. - * @param _stakeValue The stake value of asset. * @return uint256 representing multiplied positions + * @return bool returns true if multplier applied */ - function checkMultiplier(address _asset, address _user, uint _predictionStake, uint predictionPoints, uint _stakeValue) public view returns(uint, bool) { + function checkMultiplier(address _user, uint predictionPoints) public view returns(uint, bool) { bool multiplierApplied; - uint _stakedBalance = tokenController.tokensLockedAtTime(_user, "SM", now); - uint _predictionValueInToken; - (, _predictionValueInToken) = getValueAndMultiplierParameters(_asset, _predictionStake); - if(_stakeValue < minStakeForMultiplier) { - return (predictionPoints,multiplierApplied); - } uint _muliplier = 100; - if(_stakedBalance.div(_predictionValueInToken) > 0) { - _muliplier = _muliplier + _stakedBalance.mul(100).div(_predictionValueInToken.mul(10)); + if(userLevel[_user] > 0) { + _muliplier = _muliplier + levelMultiplier[userLevel[_user]]; multiplierApplied = true; } return (predictionPoints.mul(_muliplier).div(100),multiplierApplied); @@ -130,102 +134,65 @@ contract MarketUtility { **/ function updateUintParameters(bytes8 code, uint256 value) external - onlyAuthorized + onlyAuthorizedToGovern { - if (code == "SW") { // Stake weightage - require(value <= 100, "Value must be less or equal to 100"); - STAKE_WEIGHTAGE = value; - } else if (code == "SWMA") { // Minimum amount required for stake weightage - STAKE_WEIGHTAGE_MIN_AMOUNT = value; - } else if (code == "MTED") { // Minimum time elapsed divisor - minTimeElapsedDivisor = value; - } else if (code == "MINPRD") { // Minimum predictionamount + if (code == "MINPRD") { // Minimum predictionamount minPredictionAmount = value; - } else if (code == "MAXPRD") { // Minimum predictionamount + } else if (code == "MAXPRD") { // Maximum predictionamount maxPredictionAmount = value; } else if (code == "PDEC") { // Position's Decimals positionDecimals = value; - } else if (code == "MINSTM") { // Min stake required for applying multiplier - minStakeForMultiplier = value; - } else if (code == "RPERC") { // Risk percentage - riskPercentage = value; } else if (code == "TSDISP") { // Amount of tokens to be staked for raising a dispute tokenStakeForDispute = value; - } else { + } else if (code == "SFMS") { // Minimum amount of tokens to be staked for considering staking factor + stakingFactorMinStake = value; + } else if (code == "SFCPW") { // Staking Factor Weightage and Current Price weightage + stakingFactorWeightage = uint32(value); + currentPriceWeightage = 100 - stakingFactorWeightage; + }else { revert("Invalid code"); } } /** - * @dev Updates address parameters of config - **/ - function updateAddressParameters(bytes8 code, address payable value) - external - onlyAuthorized - { - require(value != address(0), "Value cannot be address(0)"); - if (code == "UNIFAC") { // Uniswap factory address - uniswapFactory = IUniswapV2Factory(value); - plotETHpair = uniswapFactory.getPair(plotToken, weth); - } else { - revert("Invalid code"); - } + * @dev Function to set `_marketCurr` to Cuurency Price. Callable by authorised addresses only + * @param _marketCurr currencyType + * @param _val Price of currency + */ + function setFeedPriceForMarketType(bytes32 _marketCurr, uint _val) external onlyAuthorized { + address _feedAddress = allMarkets.getMarketCurrencyData(_marketCurr); // getting feed address. + require(_feedAddress == address(0)); // feed addess should be null. + marketTypeFeedPrice[_marketCurr] = _val; + } + + /** + * @dev Function to set `_asset` to PLOT token value conversion rate + * @param _asset Token Address + * @param _rate `_asset` to PLOT conversion rate + */ + function setAssetPlotConversionRate(address _asset, uint256 _rate) public onlyAuthorized { + conversionRate[_asset] = _rate; } /** - * @dev Update cumulative price of token in uniswap - **/ - function update() external onlyAuthorized { - require(plotETHpair != address(0), "Uniswap pair not set"); - UniswapPriceData storage _priceData = uniswapPairData[plotETHpair]; - ( - uint256 price0Cumulative, - uint256 price1Cumulative, - uint32 blockTimestamp - ) = UniswapV2OracleLibrary.currentCumulativePrices(plotETHpair); - uint32 timeElapsed = blockTimestamp - _priceData.blockTimestampLast; // overflow is desired - - if (timeElapsed >= updatePeriod || !_priceData.initialized) { - // overflow is desired, casting never truncates - // cumulative price is in (uq112x112 price * seconds) units so we simply wrap it after division by time elapsed - _priceData.price0Average = FixedPoint.uq112x112( - uint224( - (price0Cumulative - _priceData.price0CumulativeLast) / - timeElapsed - ) - ); - _priceData.price1Average = FixedPoint.uq112x112( - uint224( - (price1Cumulative - _priceData.price1CumulativeLast) / - timeElapsed - ) - ); - - _priceData.price0CumulativeLast = price0Cumulative; - _priceData.price1CumulativeLast = price1Cumulative; - _priceData.blockTimestampLast = blockTimestamp; - if(!_priceData.initialized) { - _priceData.initialized = true; - } - } + * @dev Function to set `_user` level for prediction points multiplier + * @param _user User address + * @param _level user level indicator + */ + function setUserLevel(address _user, uint256 _level) public onlyAuthorized { + userLevel[_user] = _level; } /** - * @dev Set initial PLOT/ETH pair cummulative price - **/ - function setInitialCummulativePrice() public { - require(msg.sender == initiater); - require(plotETHpair == address(0),"Already initialised"); - plotETHpair = uniswapFactory.getPair(plotToken, weth); - UniswapPriceData storage _priceData = uniswapPairData[plotETHpair]; - ( - uint256 price0Cumulative, - uint256 price1Cumulative, - uint32 blockTimestamp - ) = UniswapV2OracleLibrary.currentCumulativePrices(plotETHpair); - _priceData.price0CumulativeLast = price0Cumulative; - _priceData.price1CumulativeLast = price1Cumulative; - _priceData.blockTimestampLast = blockTimestamp; + * @dev Function to set multiplier per level (With 2 decimals) + * @param _userLevels Array of levels + * @param _multipliers Array of corresponding multipliers + */ + function setMultiplierLevels(uint256[] memory _userLevels, uint256[] memory _multipliers) public onlyAuthorizedToGovern { + require(_userLevels.length == _multipliers.length); + for(uint256 i = 0; i < _userLevels.length; i++) { + levelMultiplier[_userLevels[i]] = _multipliers[i]; + } } /** @@ -238,7 +205,6 @@ contract MarketUtility { /** * @dev Get basic market details * @return Minimum amount required to predict in market - * @return Percentage of users leveraged amount to deduct when placed in wrong prediction * @return Decimal points for prediction positions * @return Maximum prediction amount **/ @@ -246,55 +212,50 @@ contract MarketUtility { public view returns ( - uint256, uint256, uint256, uint256 ) { - return (minPredictionAmount, riskPercentage, positionDecimals, maxPredictionAmount); + return (minPredictionAmount, positionDecimals, maxPredictionAmount); } /** * @dev Get Parameter required for option price calculation - * @param _marketFeedAddress Feed Address of currency on which market options are based on - * @return Stake weightage percentage for calculation option price - * @return minimum amount of stake required to consider stake weightage - * @return Current price of the market currency - * @return Divisor to calculate minimum time elapsed for a market type **/ - function getPriceCalculationParams( - address _marketFeedAddress - ) + function getPriceCalculationParams() public view returns ( uint256, uint256, - uint256, - uint256 + uint32 ) { - uint256 _currencyPrice = getAssetPriceUSD( - _marketFeedAddress - ); return ( - STAKE_WEIGHTAGE, - STAKE_WEIGHTAGE_MIN_AMOUNT, - _currencyPrice, - minTimeElapsedDivisor + stakingFactorMinStake, + stakingFactorWeightage, + currentPriceWeightage ); } /** * @dev Get price of provided feed address * @param _currencyFeedAddress Feed Address of currency on which market options are based on + * @param _marketCurr name of currency type * @return Current price of the market currency **/ function getAssetPriceUSD( - address _currencyFeedAddress + address _currencyFeedAddress, + bytes32 _marketCurr ) public view returns (uint256 latestAnswer) { - return uint256(IChainLinkOracle(_currencyFeedAddress).latestAnswer()); + + if(_currencyFeedAddress == address(0)) { + return marketTypeFeedPrice[_marketCurr]; // If feed address is null, return manually feeded value + } else { + return uint256(IChainLinkOracle(_currencyFeedAddress).latestAnswer()); // If feed address is available, return value from feed contract + } + } /** @@ -321,41 +282,6 @@ contract MarketUtility { (uint256(currentRoundAnswer), currentRoundId); } - /** - * @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) - { - tokenEthValue = _amount; - if (_currencyAddress != ETH_ADDRESS) { - tokenEthValue = getPrice(plotETHpair, _amount); - } - } - - /** - * @dev Get price of provided currency address in ETH - * @param _currencyAddress Address of currency - * @return Price of provided currency in ETH - * @return Decimals of the currency - **/ - function getAssetPriceInETH(address _currencyAddress) - public - view - returns (uint256 tokenEthValue, uint256 decimals) - { - tokenEthValue = 1; - if (_currencyAddress != ETH_ADDRESS) { - decimals = IToken(_currencyAddress).decimals(); - tokenEthValue = getPrice(plotETHpair, 10**decimals); - } - } - /** * @dev Get amount of stake required to raise a dispute **/ @@ -363,154 +289,131 @@ contract MarketUtility { return tokenStakeForDispute; } - /** - * @dev Get value of _asset in PLOT token and multiplier parameters - * @param _asset Address of asset for which value is requested - * @param _amount Amount of _asset - * @return min prediction amount required for multiplier - * @return value of given asset in PLOT tokens - **/ - function getValueAndMultiplierParameters(address _asset, uint256 _amount) - public - view - returns (uint256, uint256) - { - uint256 _value = _amount; - if (_asset == ETH_ADDRESS) { - _value = (uniswapPairData[plotETHpair].price1Average) - .mul(_amount) - .decode144(); - } - return (minStakeForMultiplier, _value); + function calculateOptionRange(uint _optionRangePerc, uint64 _decimals, uint8 _roundOfToNearest, address _marketFeed, bytes32 _marketCurr) external view returns(uint64 _minValue, uint64 _maxValue) { + uint currentPrice = getAssetPriceUSD(_marketFeed, _marketCurr); + uint optionRangePerc = currentPrice.mul(_optionRangePerc.div(2)).div(10000); + _minValue = uint64((ceil(currentPrice.sub(optionRangePerc).div(_roundOfToNearest), 10**_decimals)).mul(_roundOfToNearest)); + _maxValue = uint64((ceil(currentPrice.add(optionRangePerc).div(_roundOfToNearest), 10**_decimals)).mul(_roundOfToNearest)); } - /** - * @dev Get Market feed address - * @return Uniswap factory address - **/ - function getFeedAddresses() public view returns (address) { - return (address(uniswapFactory)); + function calculatePredictionPoints(uint _marketId, uint256 _prediction, address _user, bool multiplierApplied, uint _predictionStake) external view returns(uint64 predictionPoints, bool isMultiplierApplied) { + uint _stakeValue = _predictionStake.mul(1e10); + if(_stakeValue < minPredictionAmount || _stakeValue > maxPredictionAmount) { + return (0, isMultiplierApplied); + } + uint64 _optionPrice = getOptionPrice(_marketId, _prediction); + predictionPoints = uint64(_predictionStake).div(_optionPrice); + if(!multiplierApplied) { + uint256 _predictionPoints; + (_predictionPoints, isMultiplierApplied) = checkMultiplier(_user, predictionPoints); + predictionPoints = uint64(_predictionPoints); + } } /** - * @dev Get value of token in pair + * @dev Gets price for all the options in a market + * @param _marketId Market ID + * @return _optionPrices array consisting of prices for all available options **/ - function getPrice(address pair, uint256 amountIn) - public - view - returns (uint256 amountOut) - { - amountOut = (uniswapPairData[pair].price0Average) - .mul(amountIn) - .decode144(); - } - - /** - * @dev function to calculate square root of a number - */ - function sqrt(uint x) internal pure returns (uint y) { - uint z = (x + 1) / 2; - y = x; - while (z < y) { - y = z; - z = (x / z + z) / 2; + function getAllOptionPrices(uint _marketId) external view returns(uint64[] memory _optionPrices) { + _optionPrices = new uint64[](3); + for(uint i=0;i<3;i++) { + _optionPrices[i] = getOptionPrice(_marketId,i+1); } + } /** - * @dev Calculate the prediction value, passing all the required params - * params index - * 0 _prediction - * 1 neutralMinValue - * 2 neutralMaxValue - * 3 startTime - * 4 expireTime - * 5 totalStakedETH - * 6 totalStakedToken - * 7 ethStakedOnOption - * 8 plotStakedOnOption - * 9 _stake - * 10 _leverage - */ - function calculatePredictionValue(uint[] memory params, address asset, address user, address marketFeedAddress, bool _checkMultiplier) public view returns(uint _predictionValue, bool _multiplierApplied) { - uint _stakeValue = getAssetValueETH(asset, params[9]); - if(_stakeValue < minPredictionAmount || _stakeValue > maxPredictionAmount) { - return (_predictionValue, _multiplierApplied); + * @dev Gets price for given market and option + * @param _marketId Market ID + * @param _prediction prediction option + * @return option price + **/ + function getOptionPrice(uint _marketId, uint256 _prediction) public view returns(uint64) { + (uint[] memory _optionPricingParams, uint32 startTime, address _feedAddress) = allMarkets.getMarketOptionPricingParams(_marketId,_prediction); + uint stakingFactorConst; + uint optionPrice; + // Checking if current stake in market reached minimum stake required for considering staking factor. + if(_optionPricingParams[1] > _optionPricingParams[2]) + { + // 10000 / staking weightage + stakingFactorConst = uint(10000).div(_optionPricingParams[3]); + // (Amount staked in option x stakingFactorConst x 10^18) / Total staked in market --- (1) + optionPrice = (_optionPricingParams[0].mul(stakingFactorConst).mul(10**18).div(_optionPricingParams[1])); } - uint optionPrice; - - optionPrice = calculateOptionPrice(params, marketFeedAddress); - _predictionValue = _calculatePredictionPoints(_stakeValue.mul(positionDecimals), optionPrice, params[10]); - if(_checkMultiplier) { - return checkMultiplier(asset, user, params[9], _predictionValue, _stakeValue); + uint timeElapsed = uint(now).sub(startTime); + // max(timeElapsed, minTimePassed) + if(timeElapsed<_optionPricingParams[5]) { + timeElapsed = _optionPricingParams[5]; } - return (_predictionValue, _multiplierApplied); - } + uint[] memory _distanceData = getOptionDistanceData(_marketId,_prediction, _feedAddress); + + // (Time Elapsed x 10000) / (currentPriceWeightage x (Max Distance + 1)) + uint timeFactor = timeElapsed.mul(10000).div(_optionPricingParams[4].mul(_distanceData[0].add(1))); + + (, , , , uint totalTime, , ) = allMarkets.getMarketData(_marketId); + + // (1) + ((Option Distance from max distance + 1) x timeFactor x 10^18 / Total Prediction Time) -- (2) + optionPrice = optionPrice.add((_distanceData[1].add(1)).mul(timeFactor).mul(10**18).div(totalTime)); + // (2) / ((stakingFactorConst x 10^13) + timeFactor x 10^13 x (cummulative option distaance + 3) / Total Prediction Time) + optionPrice = optionPrice.div(stakingFactorConst.mul(10**13).add(timeFactor.mul(10**13).mul(_distanceData[2].add(3)).div(totalTime))); + + // option price for `_prediction` in 10^5 format + return uint64(optionPrice); - function _calculatePredictionPoints(uint value, uint optionPrice, uint _leverage) internal pure returns(uint) { - //leverageMultiplier = levergage + (leverage -1)*0.05; Raised by 3 decimals i.e 1000 - uint leverageMultiplier = 1000 + (_leverage-1)*50; - value = value.mul(2500).div(1e18); - // (amount*sqrt(amount*100)*leverage*100/(price*10*125000/1000)); - return value.mul(sqrt(value.mul(10000))).mul(_leverage*100*leverageMultiplier).div(optionPrice.mul(1250000000)); } /** - * @dev Calculate the option price for given params - * params - * 0 _option - * 1 neutralMinValue - * 2 neutralMaxValue - * 3 startTime - * 4 expireTime - * 5 totalStakedETH - * 6 totalStakedToken - * 7 ethStakedOnOption - * 8 plotStakedOnOption - */ - function calculateOptionPrice(uint[] memory params, address marketFeedAddress) public view returns(uint _optionPrice) { - uint _totalStaked = params[5].add(getAssetValueETH(plotToken, params[6])); - uint _assetStakedOnOption = params[7] - .add( - (getAssetValueETH(plotToken, params[8]))); - _optionPrice = 0; - uint currentPriceOption = 0; - uint256 currentPrice = getAssetPriceUSD( - marketFeedAddress - ); - uint stakeWeightage = STAKE_WEIGHTAGE; - uint predictionWeightage = 100 - stakeWeightage; - uint predictionTime = params[4].sub(params[3]); - uint minTimeElapsed = (predictionTime).div(minTimeElapsedDivisor); - if(now > params[4]) { - return 0; - } - if(_totalStaked > STAKE_WEIGHTAGE_MIN_AMOUNT) { - _optionPrice = (_assetStakedOnOption).mul(1000000).div(_totalStaked.mul(stakeWeightage)); + * @dev Gets price for given market and option + * @param _marketId Market ID + * @param _prediction prediction option + * @return Array consist of Max Distance between current option and any option, predicting Option distance from max distance, cummulative option distance + **/ + function getOptionDistanceData(uint _marketId,uint _prediction, address _feedAddress) internal view returns(uint[] memory) { + (bytes32 _marketCurr, uint minVal, uint maxVal , , , , ) = allMarkets.getMarketData(_marketId); + // [0]--> Max Distance between current option and any option, (For 3 options, if current option is 2 it will be `1`. else, it will be `2`) + // [1]--> Predicting option distance from Max distance, (MaxDistance - | currentOption - predicting option |) + // [2]--> sum of all possible option distances, + uint[] memory _distanceData = new uint256[](3); + + // Fetching current price + uint currentPrice = getAssetPriceUSD( + _feedAddress, + _marketCurr + ); + _distanceData[0] = 2; + // current option based on current price + uint currentOption; + _distanceData[2] = 3; + if(currentPrice < minVal) + { + currentOption = 1; + } else if(currentPrice > maxVal) { + currentOption = 3; + } else { + currentOption = 2; + _distanceData[0] = 1; + _distanceData[2] = 1; } - uint maxDistance; - if(currentPrice < params[1]) { - currentPriceOption = 1; - maxDistance = 2; - } else if(currentPrice > params[2]) { - currentPriceOption = 3; - maxDistance = 2; + // MaxDistance - | currentOption - predicting option | + _distanceData[1] = _distanceData[0].sub(modDiff(currentOption,_prediction)); + return _distanceData; + } + + /** + * @dev Calculates difference between `a` and `b`. + **/ + function modDiff(uint a, uint b) internal pure returns(uint) { + if(a>b) + { + return a.sub(b); } else { - currentPriceOption = 2; - maxDistance = 1; + return b.sub(a); } - uint distance = _getAbsoluteDifference(currentPriceOption, params[0]); - uint timeElapsed = now > params[3] ? now.sub(params[3]) : 0; - timeElapsed = timeElapsed > minTimeElapsed ? timeElapsed: minTimeElapsed; - _optionPrice = _optionPrice.add((((maxDistance+1).sub(distance)).mul(1000000).mul(timeElapsed)).div((maxDistance+1).mul(predictionWeightage).mul(predictionTime))); - _optionPrice = _optionPrice.div(100); } - /** - * @dev Internal function to get the absolute difference of two values - */ - function _getAbsoluteDifference(uint value1, uint value2) internal pure returns(uint) { - return value1 > value2 ? value1.sub(value2) : value2.sub(value1); + function ceil(uint256 a, uint256 m) internal pure returns (uint256) { + return ((a + m - 1) / m) * m; } } diff --git a/contracts/Master.sol b/contracts/Master.sol index 5c357f189..824b1e6dd 100644 --- a/contracts/Master.sol +++ b/contracts/Master.sol @@ -19,6 +19,7 @@ import "./external/proxy/OwnedUpgradeabilityProxy.sol"; import "./external/govblocks-protocol/Governed.sol"; import "./external/govblocks-protocol/interfaces/IMemberRoles.sol"; import "./interfaces/IMarketRegistry.sol"; +import "./interfaces/IMarketUtility.sol"; import "./interfaces/IbLOTToken.sol"; import "./interfaces/ITokenController.sol"; import "./interfaces/Iupgradable.sol"; @@ -45,14 +46,11 @@ contract Master is Governed { * @dev Initialize the Master. * @param _implementations The address of market implementation. * @param _token The address of PLOT token. - * @param _marketUtiliy The addresses of market utility. */ function initiateMaster( address[] calldata _implementations, address _token, address _defaultAddress, - address _marketUtiliy, - address payable[] calldata _configParams, address _vesting ) external { OwnedUpgradeabilityProxy proxy = OwnedUpgradeabilityProxy( @@ -66,8 +64,10 @@ contract Master is Governed { allContractNames.push("MR"); allContractNames.push("PC"); allContractNames.push("GV"); - allContractNames.push("PL"); allContractNames.push("TC"); + allContractNames.push("AM"); + allContractNames.push("MC"); + allContractNames.push("MU"); allContractNames.push("BL"); require( @@ -83,12 +83,7 @@ contract Master is Governed { _setMasterAddress(); - IMarketRegistry(contractAddress["PL"]).initiate( - _defaultAddress, - _marketUtiliy, - _token, - _configParams - ); + IMarketUtility(contractAddress["MU"]).initialize(_defaultAddress); IbLOTToken(contractAddress["BL"]).initiatebLOT(_defaultAddress); ITokenController(contractAddress["TC"]).initiateVesting(_vesting); IMemberRoles(contractAddress["MR"]).setInititorAddress(_defaultAddress); diff --git a/contracts/MultiSigWallet.sol b/contracts/MultiSigWallet.sol new file mode 100644 index 000000000..11c976de0 --- /dev/null +++ b/contracts/MultiSigWallet.sol @@ -0,0 +1,392 @@ +pragma solidity 0.5.7; + + +/// @title Multisignature wallet - Allows multiple parties to agree on transactions before execution. +contract MultiSigWallet { + + /* + * Events + */ + event Confirmation(address indexed sender, uint indexed transactionId); + event Revocation(address indexed sender, uint indexed transactionId); + event Submission(uint indexed transactionId); + event Execution(uint indexed transactionId); + event ExecutionFailure(uint indexed transactionId); + event Deposit(address indexed sender, uint value); + event OwnerAddition(address indexed owner); + event OwnerRemoval(address indexed owner); + event RequirementChange(uint required); + + /* + * Constants + */ + uint constant public MAX_OWNER_COUNT = 50; + + /* + * Storage + */ + mapping (uint => Transaction) public transactions; + mapping (uint => mapping (address => bool)) public confirmations; + mapping (address => bool) public isOwner; + address[] public owners; + uint public required; + uint public transactionCount; + + struct Transaction { + address destination; + uint value; + bytes data; + bool executed; + } + + /* + * Modifiers + */ + modifier onlyWallet() { + require(msg.sender == address(this)); + _; + } + + modifier ownerDoesNotExist(address owner) { + require(!isOwner[owner]); + _; + } + + modifier ownerExists(address owner) { + require(isOwner[owner]); + _; + } + + modifier transactionExists(uint transactionId) { + require(transactions[transactionId].destination != address(0)); + _; + } + + modifier confirmed(uint transactionId, address owner) { + require(confirmations[transactionId][owner]); + _; + } + + modifier notConfirmed(uint transactionId, address owner) { + require(!confirmations[transactionId][owner]); + _; + } + + modifier notExecuted(uint transactionId) { + require(!transactions[transactionId].executed); + _; + } + + modifier notNull(address _address) { + require(_address != address(0)); + _; + } + + modifier validRequirement(uint ownerCount, uint _required) { + require(ownerCount <= MAX_OWNER_COUNT + && _required <= ownerCount + && _required != 0 + && ownerCount != 0); + _; + } + + /// @dev Fallback function allows to deposit ether. + function() + payable + external + { + if (msg.value > 0) + emit Deposit(msg.sender, msg.value); + } + + /* + * Public functions + */ + /// @dev Contract constructor sets initial owners and required number of confirmations. + /// @param _owners List of initial owners. + /// @param _required Number of required confirmations. + constructor(address[] memory _owners, uint _required) + public + validRequirement(_owners.length, _required) + { + for (uint i=0; i<_owners.length; i++) { + require(!isOwner[_owners[i]] && _owners[i] != address(0)); + isOwner[_owners[i]] = true; + } + owners = _owners; + required = _required; + } + + /// @dev Allows to add a new owner. Transaction has to be sent by wallet. + /// @param owner Address of new owner. + function addOwner(address owner) + public + onlyWallet + ownerDoesNotExist(owner) + notNull(owner) + validRequirement(owners.length + 1, required) + { + isOwner[owner] = true; + owners.push(owner); + emit OwnerAddition(owner); + } + + /// @dev Allows to remove an owner. Transaction has to be sent by wallet. + /// @param owner Address of owner. + function removeOwner(address owner) + public + onlyWallet + ownerExists(owner) + { + isOwner[owner] = false; + for (uint i=0; i owners.length) + changeRequirement(owners.length); + emit OwnerRemoval(owner); + } + + /// @dev Allows to replace an owner with a new owner. Transaction has to be sent by wallet. + /// @param owner Address of owner to be replaced. + /// @param newOwner Address of new owner. + function replaceOwner(address owner, address newOwner) + public + onlyWallet + ownerExists(owner) + ownerDoesNotExist(newOwner) + { + for (uint i=0; i uint256) public lockedForGV; - string public name = "PLOT"; - string public symbol = "PLOT"; - uint8 public decimals = 18; address public operator; modifier onlyOperator() { - require(msg.sender == operator, "Not operator"); + require(_msgSender() == operator, "Not operator"); _; } - - /** - * @dev Initialize PLOT token - * @param _initialSupply Initial token supply - * @param _initialTokenHolder Initial token holder address - */ - constructor(uint256 _initialSupply, address _initialTokenHolder) public { - _mint(_initialTokenHolder, _initialSupply); - operator = _initialTokenHolder; - } - - /** + + /** * @dev change operator address * @param _newOperator address of new operator */ @@ -56,48 +55,31 @@ contract PlotXToken is ERC20 { operator = _newOperator; return true; } - - /** - * @dev burns an amount of the tokens of the message sender - * account. - * @param amount The amount that will be burnt. - */ - function burn(uint256 amount) public { - _burn(msg.sender, amount); - } - - /** - * @dev Burns a specific amount of tokens from the target address and decrements allowance - * @param from address The address which you want to send tokens from - * @param value uint256 The amount of token to be burned - */ - function burnFrom(address from, uint256 value) public { - _burnFrom(from, value); - } - - /** - * @dev function that mints an amount of the token and assigns it to - * an account. - * @param account The account that will receive the created tokens. - * @param amount The amount that will be created. + + /** + * @dev Lock the user's tokens + * @param _of user's address. */ - function mint(address account, uint256 amount) + function lockForGovernanceVote(address _of, uint256 _period) public onlyOperator - returns (bool) { - _mint(account, amount); - return true; + if (_period.add(now) > lockedForGV[_of]) + lockedForGV[_of] = _period.add(now); } - /** + function isLockedForGV(address _of) public view returns (bool) { + return (lockedForGV[_of] > now); + } + + /** * @dev Transfer token for a specified address * @param to The address to transfer to. * @param value The amount to be transferred. */ function transfer(address to, uint256 value) public returns (bool) { - require(lockedForGV[msg.sender] < now, "Locked for governance"); // if not voted under governance - _transfer(msg.sender, to, value); + require(lockedForGV[_msgSender()] < now, "Locked for governance"); // if not voted under governance + _transfer(_msgSender(), to, value); return true; } @@ -113,23 +95,42 @@ contract PlotXToken is ERC20 { uint256 value ) public returns (bool) { require(lockedForGV[from] < now, "Locked for governance"); // if not voted under governance - _transferFrom(from, to, value); + super.transferFrom(from, to, value); return true; } + + // This is to support Native meta transactions + // never use msg.sender directly, use _msgSender() instead + function _msgSender() + internal + view + returns (address payable sender) + { + return NativeMetaTransaction._msgSender(); + } /** - * @dev Lock the user's tokens - * @param _of user's address. + * @notice called when token is deposited on root chain + * @dev Should be callable only by ChildChainManager + * Should handle deposit by minting the required amount for user + * Make sure minting is done only by this function + * @param user user address for whom deposit is being done + * @param depositData abi encoded amount */ - function lockForGovernanceVote(address _of, uint256 _period) - public - onlyOperator + function deposit(address user, bytes calldata depositData) + external + only(DEPOSITOR_ROLE) { - if (_period.add(now) > lockedForGV[_of]) - lockedForGV[_of] = _period.add(now); + uint256 amount = abi.decode(depositData, (uint256)); + _mint(user, amount); } - function isLockedForGV(address _of) public view returns (bool) { - return (lockedForGV[_of] > now); + /** + * @notice called when user wants to withdraw tokens back to root chain + * @dev Should burn user's tokens. This transaction will be verified when exiting on root chain + * @param amount amount of tokens to withdraw + */ + function withdraw(uint256 amount) external { + _burn(_msgSender(), amount); } -} +} \ No newline at end of file diff --git a/contracts/ProposalCategory.sol b/contracts/ProposalCategory.sol index 2335421c4..25bd9ba51 100644 --- a/contracts/ProposalCategory.sol +++ b/contracts/ProposalCategory.sol @@ -55,8 +55,8 @@ contract ProposalCategory is Governed, IProposalCategory, Iupgradable { initiated = true; uint256 advisoryBoardRole = uint256(IMemberRoles.Role.AdvisoryBoard); - uint256 tokenHolder = uint256(IMemberRoles.Role.TokenHolder); uint256 disputeResolutionBoard = uint256(IMemberRoles.Role.DisputeResolution); + uint256 tokenHolder = uint256(IMemberRoles.Role.TokenHolder); _addInitialCategories("Uncategorized", "", "EX", "", 0, 0); _addInitialCategories( @@ -91,51 +91,51 @@ contract ProposalCategory is Governed, IProposalCategory, Iupgradable { 50, advisoryBoardRole ); //4 - _addInitialCategories( - "Update Market Implementations", - "QmbyrHnGgTU9WWFq7DgtRTdpExLg9MqcFRYpWNpo7Ezjd5", - "PL", - "updateMarketImplementations(uint256[],address[])", - 60, - tokenHolder - ); // 5 + // _addInitialCategories( + // "Update Market Implementations", + // "QmbyrHnGgTU9WWFq7DgtRTdpExLg9MqcFRYpWNpo7Ezjd5", + // "PL", + // "updateMarketImplementations(uint256[],address[])", + // 60, + // advisoryBoardRole + // ); // 5 _addInitialCategories( "Update contract's Implementation", "QmesiuX929bJHmgH8E58L6FWPazcLdgcdjmFzinEdsMfre", - "PL", + "AM", "upgradeContractImplementation(address,address)", 60, - tokenHolder - ); // 6 + advisoryBoardRole + ); // 5 _addInitialCategories( "Upgrade multiple contract Implementations", "QmcL1jUk7oda2cumSUTCrF6vTSeQN7qd1bYDFdz3v7BbUH", "MS", "upgradeMultipleImplementations(bytes2[],address[])", 50, - tokenHolder - ); // 7 + advisoryBoardRole + ); // 6 _addInitialCategories( "Update master Implementation", "QmPrGbWA4cuWzZbc9ZmqFmSRSFJnp5sa747wKsJnQkkj4t", "MS", "upgradeTo(address)", 50, - tokenHolder - ); // 8 + advisoryBoardRole + ); // 7 _addInitialCategories( "Add new contract", "QmXq5Jb4oeNzD2NHBLuWqy2m9J4N1KtkwyirBjkPBRNHii", "MS", "addNewContract(bytes2,address)", 50, - tokenHolder + advisoryBoardRole ); _addInitialCategories( "Raise Dispute", "QmQLKazba2dL8nTtGaoon6DsPv5FcpKqWZPRdxLv2tfUQW", - "PL", - "resolveDispute(address,uint256)", + "AM", + "resolveDispute(uint256,uint256)", 60, disputeResolutionBoard ); @@ -145,15 +145,15 @@ contract ProposalCategory is Governed, IProposalCategory, Iupgradable { "TC", "burnLockedTokens(address,bytes32,uint256)", 60, - tokenHolder - ); //11 + advisoryBoardRole + ); //10 _addInitialCategories( "Swap AB member", "QmV5HJMmhkEiHWt5qdNp6AbCqcn9Lw9ASA9efHDKGm8mdh", "MR", "swapABMember(address,address)", 60, - tokenHolder + advisoryBoardRole ); _addInitialCategories( "Update governance parameters", @@ -161,7 +161,7 @@ contract ProposalCategory is Governed, IProposalCategory, Iupgradable { "GV", "updateUintParameters(bytes8,uint256)", 60, - tokenHolder + advisoryBoardRole ); _addInitialCategories( "Update Token Controller parameters", @@ -169,79 +169,103 @@ contract ProposalCategory is Governed, IProposalCategory, Iupgradable { "TC", "updateUintParameters(bytes8,uint256)", 60, - tokenHolder + advisoryBoardRole ); _addInitialCategories( "Add new market type", "QmPwAdEj6quzB65JWr6hDz6HrLtjTfbezwUiAe6mBq2sxY", - "PL", - "addNewMarketType(uint64,uint64,uint64)", + "AM", + "addMarketType(uint32,uint32,uint32,uint32,uint32)", 60, - tokenHolder - ); //15 + advisoryBoardRole + ); //14 _addInitialCategories( "Add new market currency", "QmTu2FnkqUWhhNbeQraSrtbdA4DfGLavTsLRKRCeLV51x1", - "PL", - "addNewMarketCurrency(address,uint64)", + "AM", + "addMarketCurrency(bytes32,address,uint8,uint8,uint32)", 60, - tokenHolder + advisoryBoardRole ); _addInitialCategories( "Pause Market Creation", "QmamFs4k5ZbzajipsbWb4LCaKtyxDUwb9U5dYiNFqExb2W", - "PL", + "AM", "pauseMarketCreation()", 60, - tokenHolder + advisoryBoardRole ); _addInitialCategories( "Resume Market Creation", "QmZ9W1gHTJjSnt3ieiNv1Ux6ooX7ngU4Jrpvk3QiiBeP5r", - "PL", + "AM", "resumeMarketCreation()", 60, - tokenHolder + advisoryBoardRole ); _addInitialCategories( - "Transfer Market Registry Assets", + "Transfer Assets", "QmeRCfGJuA6oTqY8a7nuVxdHih2SmZUTaZLVrttGv6yKy5", - "PL", + "MC", "transferAssets(address,address,uint256)", 60, - tokenHolder + advisoryBoardRole ); _addInitialCategories( - "Update Market Uint parameters", + "Update Market Creation Reward Uint parameters", "QmXPXBkSKfidTgbDcRBLqokqAa9SU2wwErTyedPAZPfr5z", - "PL", + "MC", "updateUintParameters(bytes8,uint256)", 60, - tokenHolder - ); //20 - _addInitialCategories( - "Update Market Address parameters", - "QmbbNRchZHMULBbKFT8qjCWgCRPa4qdkst8mE8A2Kffy7N", - "PL", - "updateConfigAddressParameters(bytes8,address)", - 60, - tokenHolder - ); + advisoryBoardRole + ); //19 + // _addInitialCategories( + // "Update Market Address parameters", + // "QmbbNRchZHMULBbKFT8qjCWgCRPa4qdkst8mE8A2Kffy7N", + // "PL", + // "updateConfigAddressParameters(bytes8,address)", + // 60, + // advisoryBoardRole + // ); _addInitialCategories( "Update Member roles parameters", "QmcG8KXLMTDL5CtiKed12bJxE4ioL7Wn7oXLdW1zYWpf62", "MR", "updateUintParameters(bytes8,uint256)", 60, - tokenHolder - ); //22 + advisoryBoardRole + ); //20 _addInitialCategories( "Whitelist Sponsor", "QmRB2twfkzjox4ZAStnZTvtqr7Tr7ByGVdjTziWnpxXmWw", "MS", "whitelistSponsor(address)", 60, - tokenHolder + advisoryBoardRole + ); + _addInitialCategories( + "Toggle market creation of Type", + "", + "AM", + "toggleMarketCreationType(uint64,bool)", + 60, + advisoryBoardRole + ); + _addInitialCategories( + "Set Multiplier per level", + "", + "MU", + "setMultiplierLevels(uint256[],uint256[])", + 60, + advisoryBoardRole + ); + _addInitialCategories( + "Update Market Utility Uint parameters", + "QmXPXBkSKfidTgbDcRBLqokqAa9SU2wwErTyedPAZPfr5z", + "MU", + "updateUintParameters(bytes8,uint256)", + 60, + advisoryBoardRole ); _addInitialCategories( "Any other item", @@ -249,7 +273,7 @@ contract ProposalCategory is Governed, IProposalCategory, Iupgradable { "EX", "", 60, - tokenHolder + advisoryBoardRole ); } diff --git a/contracts/Staking.sol b/contracts/Staking.sol index 20b9ec8a5..00588b87f 100644 --- a/contracts/Staking.sol +++ b/contracts/Staking.sol @@ -12,7 +12,7 @@ pragma solidity 0.5.7; -import "./PlotXToken.sol"; +import "./interfaces/IToken.sol"; import "./external/openzeppelin-solidity/math/SafeMath.sol"; import "./external/openzeppelin-solidity/token/ERC20/ERC20.sol"; @@ -47,7 +47,7 @@ contract Staking { ERC20 private stakeToken; // Reward token - PlotXToken private rewardToken; + IToken private rewardToken; // Interest and staker data InterestData public interestData; @@ -107,7 +107,7 @@ contract Staking { require(_rewardToken != address(0), "Can not be null address"); require(_vaultAdd != address(0), "Can not be null address"); stakeToken = ERC20(_stakeToken); - rewardToken = PlotXToken(_rewardToken); + rewardToken = IToken(_rewardToken); stakingStartTime = _stakingStart; interestData.lastUpdated = _stakingStart; stakingPeriod = _stakingPeriod; diff --git a/contracts/TokenController.sol b/contracts/TokenController.sol index 43a0361d0..c932df128 100644 --- a/contracts/TokenController.sol +++ b/contracts/TokenController.sol @@ -16,16 +16,15 @@ pragma solidity 0.5.7; import "./external/lockable-token/IERC1132.sol"; -import "./PlotXToken.sol"; import "./interfaces/IbLOTToken.sol"; import "./Vesting.sol"; import "./interfaces/Iupgradable.sol"; import "./interfaces/IToken.sol"; -import "./interfaces/IMarketRegistry.sol"; import "./external/govblocks-protocol/Governed.sol"; import "./external/proxy/OwnedUpgradeabilityProxy.sol"; +import "./external/NativeMetaTransaction.sol"; -contract TokenController is IERC1132, Governed, Iupgradable { +contract TokenController is IERC1132, Governed, Iupgradable, NativeMetaTransaction { using SafeMath for uint256; event Burned(address indexed member, bytes32 lockedUnder, uint256 amount); @@ -41,13 +40,12 @@ contract TokenController is IERC1132, Governed, Iupgradable { bool internal constructorCheck; - PlotXToken public token; - IMarketRegistry public marketRegistry; + IToken public token; IbLOTToken public bLOTToken; Vesting public vesting; modifier onlyAuthorized { - require(marketRegistry.isMarket(msg.sender), "Not authorized"); + require(IMaster(masterAddress).isInternal(msg.sender), "Not authorized"); _; } @@ -62,9 +60,9 @@ contract TokenController is IERC1132, Governed, Iupgradable { constructorCheck = true; masterAddress = msg.sender; IMaster ms = IMaster(msg.sender); - token = PlotXToken(ms.dAppToken()); + token = IToken(ms.dAppToken()); bLOTToken = IbLOTToken(ms.getLatestAddress("BL")); - marketRegistry = IMarketRegistry(address(uint160(ms.getLatestAddress("PL")))); + _initializeEIP712("TC"); } /** @@ -130,18 +128,18 @@ contract TokenController is IERC1132, Governed, Iupgradable { { require((_reason == "SM" && _time == smLockPeriod) || _reason == "DR", "Unspecified reason or time"); - require(tokensLocked(msg.sender, _reason) == 0, ALREADY_LOCKED); + require(tokensLocked(_msgSender(), _reason) == 0, ALREADY_LOCKED); require(_amount != 0, AMOUNT_ZERO); uint256 validUntil = _time.add(now); //solhint-disable-line - lockReason[msg.sender].push(_reason); + lockReason[_msgSender()].push(_reason); - require(token.transferFrom(msg.sender, address(this), _amount)); + require(token.transferFrom(_msgSender(), address(this), _amount)); - locked[msg.sender][_reason] = LockToken(_amount, validUntil, false); + locked[_msgSender()][_reason] = LockToken(_amount, validUntil, false); - emit Locked(msg.sender, _reason, _amount, validUntil); + emit Locked(_msgSender(), _reason, _amount, validUntil); return true; } @@ -211,15 +209,15 @@ contract TokenController is IERC1132, Governed, Iupgradable { { require(_reason == "SM" || _reason == "DR","Unspecified reason"); require(_amount != 0, AMOUNT_ZERO); - require(tokensLocked(msg.sender, _reason) > 0, NOT_LOCKED); - require(token.transferFrom(msg.sender, address(this), _amount)); + require(tokensLocked(_msgSender(), _reason) > 0, NOT_LOCKED); + require(token.transferFrom(_msgSender(), address(this), _amount)); - locked[msg.sender][_reason].amount = locked[msg.sender][_reason].amount.add(_amount); + locked[_msgSender()][_reason].amount = locked[_msgSender()][_reason].amount.add(_amount); if(_reason == "SM") { - locked[msg.sender][_reason].validity = locked[msg.sender][_reason].validity.add(smLockPeriod); + locked[_msgSender()][_reason].validity = locked[_msgSender()][_reason].validity.add(smLockPeriod); } - emit Locked(msg.sender, _reason, locked[msg.sender][_reason].amount, locked[msg.sender][_reason].validity); + emit Locked(_msgSender(), _reason, locked[_msgSender()][_reason].amount, locked[_msgSender()][_reason].validity); return true; } @@ -236,11 +234,11 @@ contract TokenController is IERC1132, Governed, Iupgradable { require(_time == smLockPeriod, "Must be smLockPeriod"); } require(_time != 0, "Time cannot be zero"); - require(tokensLocked(msg.sender, _reason) > 0, NOT_LOCKED); + require(tokensLocked(_msgSender(), _reason) > 0, NOT_LOCKED); - locked[msg.sender][_reason].validity = locked[msg.sender][_reason].validity.add(_time); + locked[_msgSender()][_reason].validity = locked[_msgSender()][_reason].validity.add(_time); - emit Locked(msg.sender, _reason, locked[msg.sender][_reason].amount, locked[msg.sender][_reason].validity); + emit Locked(_msgSender(), _reason, locked[_msgSender()][_reason].amount, locked[_msgSender()][_reason].validity); return true; } @@ -322,7 +320,9 @@ contract TokenController is IERC1132, Governed, Iupgradable { locked[_of][_reason].claimed = true; _removeReason(_of, _reason); } - token.burn(_amount); + OwnedUpgradeabilityProxy proxy = OwnedUpgradeabilityProxy(address(uint160(address(this)))); + IMaster ms = IMaster(proxy.proxyOwner()); + token.transfer(ms.getLatestAddress("MC"),_amount); emit Burned(_of, _reason, _amount); } diff --git a/contracts/Vesting.sol b/contracts/Vesting.sol index fc76d179c..a8458f159 100644 --- a/contracts/Vesting.sol +++ b/contracts/Vesting.sol @@ -15,7 +15,7 @@ pragma solidity 0.5.7; -import "./PlotXToken.sol"; +import "./interfaces/IToken.sol"; import "./external/openzeppelin-solidity/math/SafeMath.sol"; import "./external/openzeppelin-solidity/token/ERC20/ERC20.sol"; @@ -24,7 +24,7 @@ contract Vesting { using SafeMath for uint256; using SafeMath64 for uint64; - PlotXToken public token; + IToken public token; address public owner; uint constant internal SECONDS_PER_DAY = 1 days; @@ -56,7 +56,7 @@ contract Vesting { nonZeroAddress(_token) nonZeroAddress(_owner) { - token = PlotXToken(_token); + token = IToken(_token); owner = _owner; } diff --git a/contracts/bPlotsMigration.sol b/contracts/bPlotsMigration.sol new file mode 100644 index 000000000..ef970fbfc --- /dev/null +++ b/contracts/bPlotsMigration.sol @@ -0,0 +1,316 @@ +/* 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/token/ERC20/ERC20.sol"; +import "./external/openzeppelin-solidity/access/Roles.sol"; +import "./external/proxy/OwnedUpgradeabilityProxy.sol"; +import "./interfaces/IMaster.sol"; +import "./interfaces/Iupgradable.sol"; + +contract BLOT is Iupgradable { + using SafeMath for uint256; + using Roles for Roles.Role; + + string public constant name = "PlotXBonusToken"; + string public constant symbol = "bPLOT"; + uint8 public constant decimals = 18; + + Roles.Role private _minters; + + address public operator; + address public plotToken; + address public authController = 0x6f9f333de6eCFa67365916cF95873a4DC480217a; + address public migrationController = 0x3A6D2faBDf51Af157F3fC79bb50346a615c08BF6; + + mapping(bytes32 => MigrationStatus) public migrationStatus; + struct MigrationStatus{ + bool initiated; + bool completed; + } + + event MinterAdded(address indexed account); + event MinterRemoved(address indexed account); + event MigrationAuthorised(bytes hash); + event MigrationCompleted(bytes hash); + + mapping (address => uint256) internal _balances; + + bool private initiated; + uint256 private _totalSupply; + + /** + * @dev Emitted when `value` tokens are moved from one account (`from`) to + * another (`to`). + * + * Note that `value` may be zero. + */ + event Transfer(address indexed from, address indexed to, uint256 value); + + /** + * @dev Emitted when `value` tokens are moved from one account (`from`) to + * another (`to`). + * + * Note that `value` may be zero. + */ + event Migrate(address indexed from, address indexed to, uint256 value); + + /** + * @dev Checks if msg.sender is token operator address. + */ + modifier onlyOperator() { + require(msg.sender == operator, "Only operator"); + _; + } + + modifier onlyMinter() { + require( + isMinter(msg.sender), + "MinterRole: caller does not have the Minter role" + ); + _; + } + + /** + * @dev Initiates the BLOT with default minter address + */ + function initiatebLOT(address _defaultMinter) public { + require(!initiated); + initiated = true; + _addMinter(_defaultMinter); + } + + /** + * @dev Changes the master address and update it's instance + */ + function setMasterAddress() public { + OwnedUpgradeabilityProxy proxy = OwnedUpgradeabilityProxy( + address(uint160(address(this))) + ); + require(msg.sender == proxy.proxyOwner(), "Sender is not proxy owner."); + require(plotToken == address(0), "Already Initialized"); + IMaster ms = IMaster(msg.sender); + plotToken = ms.dAppToken(); + operator = ms.getLatestAddress("TC"); + } + + + /** + * @dev See `IERC20.transfer`. + * + * Requirements: + * + * - `recipient` cannot be the zero address. + * - the caller must have a balance of at least `amount`. + * Transfer is restricted to minter only + */ + function transfer(address recipient, uint256 amount) + public + onlyMinter + returns (bool) + { + _transfer(msg.sender, recipient, amount); + return true; + } + + /** + * @dev Moves tokens `amount` from `sender` to `recipient`. + * + * This is internal function is equivalent to `transfer`, and can be used to + * e.g. implement automatic token fees, slashing mechanisms, etc. + * + * Emits a `Transfer` event. + * + * Requirements: + * + * - `sender` cannot be the zero address. + * - `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + */ + function _transfer( + address sender, + address recipient, + uint256 amount + ) internal { + require(sender != address(0), "ERC20: transfer from the zero address"); + require(recipient != address(0), "ERC20: transfer to the zero address"); + + _balances[sender] = _balances[sender].sub(amount); + _balances[recipient] = _balances[recipient].add(amount); + emit Transfer(sender, recipient, amount); + } + + /** + * @dev See `ERC20._mint`. + * + * Requirements: + * + * - the caller must have the `MinterRole`. + * - equivalant number of PLOT will be transferred from sender to this contract + */ + function mint(address account, uint256 amount) + public + onlyMinter + returns (bool) + { + require( + IERC20(plotToken).transferFrom(msg.sender, address(this), amount), + "Error in transfer" + ); + _mint(account, amount); + return true; + } + + /** @dev Creates `amount` tokens and assigns them to `account`, increasing + * the total supply. + * + * Emits a `Transfer` event with `from` set to the zero address. + * + * Requirements + * + * - `to` cannot be the zero address. + */ + function _mint(address account, uint256 amount) internal { + require(account != address(0), "ERC20: mint to the zero address"); + + _totalSupply = _totalSupply.add(amount); + _balances[account] = _balances[account].add(amount); + emit Transfer(address(0), account, amount); + } + + function migrationHash( bytes memory _hash, address _to, address _from, uint256 _timestamp,uint256 _amount) internal pure returns (bytes32){ + return keccak256(abi.encode(_hash, _from, _to, _timestamp,_amount)); + } + + + + /** + * @dev Whitelist transaction to transfer bPlots. + * + * See `ERC20._mint`. + */ + function whitelistMigration( + bytes memory _hash, + address _to, + address _from, + uint256 _timestamp, + uint256 _amount + ) public returns (bytes32) { + require(msg.sender == authController, "msg.sender is not authController"); + require(migrationStatus[ migrationHash(_hash, _from, _to, _timestamp, _amount)].initiated == false, "Migration is already initiated"); + require(migrationStatus[ migrationHash(_hash, _from, _to, _timestamp, _amount)].completed == false, "Migration has been already completed"); + + migrationStatus[ migrationHash(_hash, _from, _to, _timestamp, _amount)].initiated = true; + emit MigrationAuthorised(_hash); + + return migrationHash(_hash, _from, _to, _timestamp, _amount); + + } + + + /** + * @dev Mint bPlots as per whitelisted transaction. + * + */ + function migrate( + bytes memory _hash, + address _to, + address _from, + uint256 _timestamp, + uint256 _amount + ) public returns (bool){ + require(msg.sender == migrationController, "msg.sender is not migration controller"); + require(migrationStatus[ migrationHash(_hash, _from, _to, _timestamp, _amount)].initiated == true, "Migration is already initiated"); + require(migrationStatus[ migrationHash(_hash, _from, _to, _timestamp, _amount)].completed == false, "Migration has been already completed"); + + _mint( _to, _amount); + migrationStatus[ migrationHash(_hash, _from, _to, _timestamp, _amount)].completed = true; + emit MigrationCompleted(_hash); + + return true; + } + + /** + * @dev Destoys `amount` tokens from `account`, reducing the + * total supply. + * + * Emits a `Transfer` event with `to` set to the zero address. + * + * Requirements + * + * - `account` cannot be the zero address. + * - `account` must have at least `amount` tokens. + */ + function _burn(address account, uint256 value) internal { + require(account != address(0), "ERC20: burn from the zero address"); + + _totalSupply = _totalSupply.sub(value); + _balances[account] = _balances[account].sub(value); + emit Transfer(account, address(0), value); + } + + /** + * @dev Check if `account` has minting rights + */ + function isMinter(address account) public view returns (bool) { + return _minters.has(account); + } + + /** + * @dev Add `account` as minter + */ + function addMinter(address account) public onlyMinter { + _addMinter(account); + } + + /** + * @dev Renounce self as minter + */ + function renounceMinter() public { + _removeMinter(msg.sender); + } + + /** + * @dev Add `account` as minter + */ + function _addMinter(address account) internal { + _minters.add(account); + emit MinterAdded(account); + } + + /** + * @dev Remove `account` from minter role + */ + function _removeMinter(address account) internal { + _minters.remove(account); + emit MinterRemoved(account); + } + + /** + * @dev See `IERC20.totalSupply`. + */ + function totalSupply() public view returns (uint256) { + return _totalSupply; + } + + /** + * @dev See `IERC20.balanceOf`. + */ + function balanceOf(address account) public view returns (uint256) { + return _balances[account]; + } + +} diff --git a/contracts/external/BasicMetaTransaction.sol b/contracts/external/BasicMetaTransaction.sol new file mode 100644 index 000000000..0a14b2b5e --- /dev/null +++ b/contracts/external/BasicMetaTransaction.sol @@ -0,0 +1,76 @@ +pragma solidity >=0.4.0 <0.7.0; + +import "./openzeppelin-solidity/math/SafeMath.sol"; + + +contract BasicMetaTransaction { + + using SafeMath for uint256; + + event MetaTransactionExecuted(address userAddress, address payable relayerAddress, bytes functionSignature); + mapping(address => uint256) private nonces; + + function getChainID() public pure returns (uint256) { + uint256 id; + assembly { + id := 137 + } + return id; + } + + /** + * Main function to be called when user wants to execute meta transaction. + * The actual function to be called should be passed as param with name functionSignature + * Here the basic signature recovery is being used. Signature is expected to be generated using + * personal_sign method. + * @param userAddress Address of user trying to do meta transaction + * @param functionSignature Signature of the actual function to be called via meta transaction + * @param sigR R part of the signature + * @param sigS S part of the signature + * @param sigV V part of the signature + */ + function executeMetaTransaction(address userAddress, bytes memory functionSignature, + bytes32 sigR, bytes32 sigS, uint8 sigV) public payable returns(bytes memory) { + + require(verify(userAddress, nonces[userAddress], getChainID(), functionSignature, sigR, sigS, sigV), "Signer and signature do not match"); + nonces[userAddress] = nonces[userAddress].add(1); + + // Append userAddress at the end to extract it from calling context + (bool success, bytes memory returnData) = address(this).call(abi.encodePacked(functionSignature, userAddress)); + + require(success, "Function call not successful"); + emit MetaTransactionExecuted(userAddress, msg.sender, functionSignature); + return returnData; + } + + function getNonce(address user) external view returns(uint256 nonce) { + nonce = nonces[user]; + } + + // Builds a prefixed hash to mimic the behavior of eth_sign. + function prefixed(bytes32 hash) internal pure returns (bytes32) { + return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash)); + } + + function verify(address owner, uint256 nonce, uint256 chainID, bytes memory functionSignature, + bytes32 sigR, bytes32 sigS, uint8 sigV) public view returns (bool) { + + bytes32 hash = prefixed(keccak256(abi.encodePacked(nonce, this, chainID, functionSignature))); + address signer = ecrecover(hash, sigV, sigR, sigS); + require(signer != address(0), "Invalid signature"); + return (owner == signer); + } + + function _msgSender() public view returns(address payable sender) { + if(msg.sender == address(this)) { + bytes memory array = msg.data; + uint256 index = msg.data.length; + assembly { + // Load the 32 bytes word from memory with the address on the lower 20 bytes, and mask those. + sender := and(mload(add(array, index)), 0xffffffffffffffffffffffffffffffffffffffff) + } + } else { + return msg.sender; + } + } +} diff --git a/contracts/external/EIP712/EIP712Base.sol b/contracts/external/EIP712/EIP712Base.sol new file mode 100644 index 000000000..a5a4feff0 --- /dev/null +++ b/contracts/external/EIP712/EIP712Base.sol @@ -0,0 +1,76 @@ +pragma solidity 0.5.7; + + +import "./Initializable.sol"; + +contract EIP712Base is Initializable { + struct EIP712Domain { + string name; + string version; + address verifyingContract; + bytes32 salt; + } + + string constant public ERC712_VERSION = "1"; + + bytes32 internal constant EIP712_DOMAIN_TYPEHASH = keccak256( + bytes( + "EIP712Domain(string name,string version,address verifyingContract,bytes32 salt)" + ) + ); + bytes32 internal domainSeperator; + + // supposed to be called once while initializing. + // one of the contractsa that inherits this contract follows proxy pattern + // so it is not possible to do this in a constructor + function _initializeEIP712( + string memory name + ) + internal + initializer + { + _setDomainSeperator(name); + } + + function _setDomainSeperator(string memory name) internal { + domainSeperator = keccak256( + abi.encode( + EIP712_DOMAIN_TYPEHASH, + keccak256(bytes(name)), + keccak256(bytes(ERC712_VERSION)), + address(this), + bytes32(getChainId()) + ) + ); + } + + function getDomainSeperator() public view returns (bytes32) { + return domainSeperator; + } + + function getChainId() public pure returns (uint256) { + uint256 id; + assembly { + id := 137 + } + return id; + } + + /** + * Accept message hash and returns hash message in EIP712 compatible form + * So that it can be used to recover signer from signature signed using EIP712 formatted data + * https://eips.ethereum.org/EIPS/eip-712 + * "\\x19" makes the encoding deterministic + * "\\x01" is the version byte to make it compatible to EIP-191 + */ + function toTypedMessageHash(bytes32 messageHash) + internal + view + returns (bytes32) + { + return + keccak256( + abi.encodePacked("\x19\x01", getDomainSeperator(), messageHash) + ); + } +} \ No newline at end of file diff --git a/contracts/external/EIP712/Initializable.sol b/contracts/external/EIP712/Initializable.sol new file mode 100644 index 000000000..6e885e308 --- /dev/null +++ b/contracts/external/EIP712/Initializable.sol @@ -0,0 +1,11 @@ +pragma solidity 0.5.7; + +contract Initializable { + bool inited = false; + + modifier initializer() { + require(!inited, "already inited"); + _; + inited = true; + } +} \ No newline at end of file diff --git a/contracts/external/NativeMetaTransaction.sol b/contracts/external/NativeMetaTransaction.sol new file mode 100644 index 000000000..65c9b12c6 --- /dev/null +++ b/contracts/external/NativeMetaTransaction.sol @@ -0,0 +1,125 @@ +pragma solidity 0.5.7; + +import "./EIP712/EIP712Base.sol"; +import "./openzeppelin-solidity/math/SafeMath.sol"; + +contract NativeMetaTransaction is EIP712Base { + using SafeMath for uint256; + bytes32 private constant META_TRANSACTION_TYPEHASH = keccak256( + bytes( + "MetaTransaction(uint256 nonce,address from,bytes functionSignature)" + ) + ); + event MetaTransactionExecuted( + address userAddress, + address payable relayerAddress, + bytes functionSignature + ); + mapping(address => uint256) nonces; + + /* + * Meta transaction structure. + * No point of including value field here as if user is doing value transfer then he has the funds to pay for gas + * He should call the desired function directly in that case. + */ + struct MetaTransaction { + uint256 nonce; + address from; + bytes functionSignature; + } + + function executeMetaTransaction( + address userAddress, + bytes memory functionSignature, + bytes32 sigR, + bytes32 sigS, + uint8 sigV + ) public payable returns (bytes memory) { + MetaTransaction memory metaTx = MetaTransaction({ + nonce: nonces[userAddress], + from: userAddress, + functionSignature: functionSignature + }); + + require( + verify(userAddress, metaTx, sigR, sigS, sigV), + "Signer and signature do not match" + ); + + // increase nonce for user (to avoid re-use) + nonces[userAddress] = nonces[userAddress].add(1); + + emit MetaTransactionExecuted( + userAddress, + msg.sender, + functionSignature + ); + + // Append userAddress and relayer address at the end to extract it from calling context + (bool success, bytes memory returnData) = address(this).call( + abi.encodePacked(functionSignature, userAddress) + ); + require(success, "Function call not successful"); + + return returnData; + } + + function hashMetaTransaction(MetaTransaction memory metaTx) + internal + pure + returns (bytes32) + { + return + keccak256( + abi.encode( + META_TRANSACTION_TYPEHASH, + metaTx.nonce, + metaTx.from, + keccak256(metaTx.functionSignature) + ) + ); + } + + function getNonce(address user) public view returns (uint256 nonce) { + nonce = nonces[user]; + } + + function verify( + address signer, + MetaTransaction memory metaTx, + bytes32 sigR, + bytes32 sigS, + uint8 sigV + ) internal view returns (bool) { + require(signer != address(0), "NativeMetaTransaction: INVALID_SIGNER"); + return + signer == + ecrecover( + toTypedMessageHash(hashMetaTransaction(metaTx)), + sigV, + sigR, + sigS + ); + } + + function _msgSender() + internal + view + returns (address payable sender) + { + if (msg.sender == address(this)) { + bytes memory array = msg.data; + uint256 index = msg.data.length; + assembly { + // Load the 32 bytes word from memory with the address on the lower 20 bytes, and mask those. + sender := and( + mload(add(array, index)), + 0xffffffffffffffffffffffffffffffffffffffff + ) + } + } else { + sender = msg.sender; + } + return sender; + } +} \ No newline at end of file diff --git a/contracts/external/openzeppelin-solidity/access/AccessControl.sol b/contracts/external/openzeppelin-solidity/access/AccessControl.sol new file mode 100644 index 000000000..63568d4e7 --- /dev/null +++ b/contracts/external/openzeppelin-solidity/access/AccessControl.sol @@ -0,0 +1,215 @@ +pragma solidity 0.5.7; + +import ".././utils/Context.sol"; +import ".././utils/EnumerableSet.sol"; +import ".././utils/Address.sol"; + +/** + * @dev Contract module that allows children to implement role-based access + * control mechanisms. + * + * Roles are referred to by their `bytes32` identifier. These should be exposed + * in the external API and be unique. The best way to achieve this is by + * using `public constant` hash digests: + * + * ``` + * bytes32 public constant MY_ROLE = keccak256("MY_ROLE"); + * ``` + * + * Roles can be used to represent a set of permissions. To restrict access to a + * function call, use {hasRole}: + * + * ``` + * function foo() public { + * require(hasRole(MY_ROLE, msg.sender)); + * ... + * } + * ``` + * + * Roles can be granted and revoked dynamically via the {grantRole} and + * {revokeRole} functions. Each role has an associated admin role, and only + * accounts that have a role's admin role can call {grantRole} and {revokeRole}. + * + * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means + * that only accounts with this role will be able to grant or revoke other + * roles. More complex role relationships can be created by using + * {_setRoleAdmin}. + * + * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to + * grant and revoke this role. Extra precautions should be taken to secure + * accounts that have been granted it. + */ +contract AccessControl is Context { + using EnumerableSet for EnumerableSet.AddressSet; + using Address for address; + + struct RoleData { + EnumerableSet.AddressSet members; + bytes32 adminRole; + } + + mapping (bytes32 => RoleData) private _roles; + + bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00; + + /** + * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` + * + * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite + * {RoleAdminChanged} not being emitted signaling this. + * + * _Available since v3.1._ + */ + event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole); + + /** + * @dev Emitted when `account` is granted `role`. + * + * `sender` is the account that originated the contract call, an admin role + * bearer except when using {_setupRole}. + */ + event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender); + + /** + * @dev Emitted when `account` is revoked `role`. + * + * `sender` is the account that originated the contract call: + * - if using `revokeRole`, it is the admin role bearer + * - if using `renounceRole`, it is the role bearer (i.e. `account`) + */ + event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender); + + /** + * @dev Returns `true` if `account` has been granted `role`. + */ + function hasRole(bytes32 role, address account) public view returns (bool) { + return _roles[role].members.contains(account); + } + + /** + * @dev Returns the number of accounts that have `role`. Can be used + * together with {getRoleMember} to enumerate all bearers of a role. + */ + function getRoleMemberCount(bytes32 role) public view returns (uint256) { + return _roles[role].members.length(); + } + + /** + * @dev Returns one of the accounts that have `role`. `index` must be a + * value between 0 and {getRoleMemberCount}, non-inclusive. + * + * Role bearers are not sorted in any particular way, and their ordering may + * change at any point. + * + * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure + * you perform all queries on the same block. See the following + * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] + * for more information. + */ + function getRoleMember(bytes32 role, uint256 index) public view returns (address) { + return _roles[role].members.at(index); + } + + /** + * @dev Returns the admin role that controls `role`. See {grantRole} and + * {revokeRole}. + * + * To change a role's admin, use {_setRoleAdmin}. + */ + function getRoleAdmin(bytes32 role) public view returns (bytes32) { + return _roles[role].adminRole; + } + + /** + * @dev Grants `role` to `account`. + * + * If `account` had not been already granted `role`, emits a {RoleGranted} + * event. + * + * Requirements: + * + * - the caller must have ``role``'s admin role. + */ + function grantRole(bytes32 role, address account) public { + require(hasRole(_roles[role].adminRole, _msgSender()), "AccessControl: sender must be an admin to grant"); + + _grantRole(role, account); + } + + /** + * @dev Revokes `role` from `account`. + * + * If `account` had been granted `role`, emits a {RoleRevoked} event. + * + * Requirements: + * + * - the caller must have ``role``'s admin role. + */ + function revokeRole(bytes32 role, address account) public { + require(hasRole(_roles[role].adminRole, _msgSender()), "AccessControl: sender must be an admin to revoke"); + + _revokeRole(role, account); + } + + /** + * @dev Revokes `role` from the calling account. + * + * Roles are often managed via {grantRole} and {revokeRole}: this function's + * purpose is to provide a mechanism for accounts to lose their privileges + * if they are compromised (such as when a trusted device is misplaced). + * + * If the calling account had been granted `role`, emits a {RoleRevoked} + * event. + * + * Requirements: + * + * - the caller must be `account`. + */ + function renounceRole(bytes32 role, address account) public { + require(account == _msgSender(), "AccessControl: can only renounce roles for self"); + + _revokeRole(role, account); + } + + /** + * @dev Grants `role` to `account`. + * + * If `account` had not been already granted `role`, emits a {RoleGranted} + * event. Note that unlike {grantRole}, this function doesn't perform any + * checks on the calling account. + * + * [WARNING] + * ==== + * This function should only be called from the constructor when setting + * up the initial roles for the system. + * + * Using this function in any other way is effectively circumventing the admin + * system imposed by {AccessControl}. + * ==== + */ + function _setupRole(bytes32 role, address account) internal { + _grantRole(role, account); + } + + /** + * @dev Sets `adminRole` as ``role``'s admin role. + * + * Emits a {RoleAdminChanged} event. + */ + function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal { + emit RoleAdminChanged(role, _roles[role].adminRole, adminRole); + _roles[role].adminRole = adminRole; + } + + function _grantRole(bytes32 role, address account) private { + if (_roles[role].members.add(account)) { + emit RoleGranted(role, account, _msgSender()); + } + } + + function _revokeRole(bytes32 role, address account) private { + if (_roles[role].members.remove(account)) { + emit RoleRevoked(role, account, _msgSender()); + } + } +} diff --git a/contracts/external/openzeppelin-solidity/access/AccessControlMixin.sol b/contracts/external/openzeppelin-solidity/access/AccessControlMixin.sol new file mode 100644 index 000000000..853f4da41 --- /dev/null +++ b/contracts/external/openzeppelin-solidity/access/AccessControlMixin.sol @@ -0,0 +1,20 @@ +pragma solidity 0.5.7; + + +import "./AccessControl.sol"; + + +contract AccessControlMixin is AccessControl { + string private _revertMsg; + function _setupContractId(string memory contractId) internal { + _revertMsg = string(abi.encodePacked(contractId, ": INSUFFICIENT_PERMISSIONS")); + } + + modifier only(bytes32 role) { + require( + hasRole(role, _msgSender()), + _revertMsg + ); + _; + } +} \ No newline at end of file diff --git a/contracts/external/openzeppelin-solidity/math/SafeMath.sol b/contracts/external/openzeppelin-solidity/math/SafeMath.sol index 009207ed1..051973bcc 100644 --- a/contracts/external/openzeppelin-solidity/math/SafeMath.sol +++ b/contracts/external/openzeppelin-solidity/math/SafeMath.sol @@ -124,6 +124,117 @@ library SafeMath { } } +library SafeMath128 { + /** + * @dev Returns the addition of two unsigned integers, reverting on + * overflow. + * + * Counterpart to Solidity's `+` operator. + * + * Requirements: + * - Addition cannot overflow. + */ + function add(uint128 a, uint128 b) internal pure returns (uint128) { + uint128 c = a + b; + require(c >= a, "SafeMath: addition overflow"); + + return c; + } + + /** + * @dev Returns the subtraction of two unsigned integers, reverting on + * overflow (when the result is negative). + * + * Counterpart to Solidity's `-` operator. + * + * Requirements: + * - Subtraction cannot overflow. + */ + function sub(uint128 a, uint128 b) internal pure returns (uint128) { + require(b <= a, "SafeMath: subtraction overflow"); + uint128 c = a - b; + + return c; + } + + /** + * @dev Returns the subtraction of two unsigned integers, reverting with custom message on + * overflow (when the result is negative). + * + * Counterpart to Solidity's `-` operator. + * + * Requirements: + * - Subtraction cannot overflow. + * + * _Available since v2.4.0._ + */ + function sub(uint128 a, uint128 b, string memory errorMessage) internal pure returns (uint128) { + require(b <= a, errorMessage); + uint128 c = a - b; + + return c; + } + + /** + * @dev Returns the multiplication of two unsigned integers, reverting on + * overflow. + * + * Counterpart to Solidity's `*` operator. + * + * Requirements: + * - Multiplication cannot overflow. + */ + function mul(uint128 a, uint128 b) internal pure returns (uint128) { + // Gas optimization: this is cheaper than requiring 'a' not being zero, but the + // benefit is lost if 'b' is also tested. + // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 + if (a == 0) { + return 0; + } + + uint128 c = a * b; + require(c / a == b, "SafeMath: multiplication overflow"); + + return c; + } + + /** + * @dev Returns the integer division of two unsigned integers. Reverts on + * division by zero. The result is rounded towards zero. + * + * Counterpart to Solidity's `/` operator. Note: this function uses a + * `revert` opcode (which leaves remaining gas untouched) while Solidity + * uses an invalid opcode to revert (consuming all remaining gas). + * + * Requirements: + * - The divisor cannot be zero. + */ + function div(uint128 a, uint128 b) internal pure returns (uint128) { + // Solidity only automatically asserts when dividing by 0 + require(b > 0, "SafeMath: division by zero"); + uint128 c = a / b; + // assert(a == b * c + a % b); // There is no case in which this doesn't hold + + return c; + } + + /** + * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), + * Reverts when dividing by zero. + * + * Counterpart to Solidity's `%` operator. This function uses a `revert` + * opcode (which leaves remaining gas untouched) while Solidity uses an + * invalid opcode to revert (consuming all remaining gas). + * + * Requirements: + * - The divisor cannot be zero. + */ + function mod(uint128 a, uint128 b) internal pure returns (uint128) { + require(b != 0, "SafeMath: modulo by zero"); + return a % b; + } +} + library SafeMath64 { /** * @dev Returns the addition of two unsigned integers, reverting on @@ -234,3 +345,114 @@ library SafeMath64 { return a % b; } } + +library SafeMath32 { + /** + * @dev Returns the addition of two unsigned integers, reverting on + * overflow. + * + * Counterpart to Solidity's `+` operator. + * + * Requirements: + * - Addition cannot overflow. + */ + function add(uint32 a, uint32 b) internal pure returns (uint32) { + uint32 c = a + b; + require(c >= a, "SafeMath: addition overflow"); + + return c; + } + + /** + * @dev Returns the subtraction of two unsigned integers, reverting on + * overflow (when the result is negative). + * + * Counterpart to Solidity's `-` operator. + * + * Requirements: + * - Subtraction cannot overflow. + */ + function sub(uint32 a, uint32 b) internal pure returns (uint32) { + require(b <= a, "SafeMath: subtraction overflow"); + uint32 c = a - b; + + return c; + } + + /** + * @dev Returns the subtraction of two unsigned integers, reverting with custom message on + * overflow (when the result is negative). + * + * Counterpart to Solidity's `-` operator. + * + * Requirements: + * - Subtraction cannot overflow. + * + * _Available since v2.4.0._ + */ + function sub(uint32 a, uint32 b, string memory errorMessage) internal pure returns (uint32) { + require(b <= a, errorMessage); + uint32 c = a - b; + + return c; + } + + /** + * @dev Returns the multiplication of two unsigned integers, reverting on + * overflow. + * + * Counterpart to Solidity's `*` operator. + * + * Requirements: + * - Multiplication cannot overflow. + */ + function mul(uint32 a, uint32 b) internal pure returns (uint32) { + // Gas optimization: this is cheaper than requiring 'a' not being zero, but the + // benefit is lost if 'b' is also tested. + // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 + if (a == 0) { + return 0; + } + + uint32 c = a * b; + require(c / a == b, "SafeMath: multiplication overflow"); + + return c; + } + + /** + * @dev Returns the integer division of two unsigned integers. Reverts on + * division by zero. The result is rounded towards zero. + * + * Counterpart to Solidity's `/` operator. Note: this function uses a + * `revert` opcode (which leaves remaining gas untouched) while Solidity + * uses an invalid opcode to revert (consuming all remaining gas). + * + * Requirements: + * - The divisor cannot be zero. + */ + function div(uint32 a, uint32 b) internal pure returns (uint32) { + // Solidity only automatically asserts when dividing by 0 + require(b > 0, "SafeMath: division by zero"); + uint32 c = a / b; + // assert(a == b * c + a % b); // There is no case in which this doesn't hold + + return c; + } + + /** + * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), + * Reverts when dividing by zero. + * + * Counterpart to Solidity's `%` operator. This function uses a `revert` + * opcode (which leaves remaining gas untouched) while Solidity uses an + * invalid opcode to revert (consuming all remaining gas). + * + * Requirements: + * - The divisor cannot be zero. + */ + function mod(uint32 a, uint32 b) internal pure returns (uint32) { + require(b != 0, "SafeMath: modulo by zero"); + return a % b; + } +} \ No newline at end of file diff --git a/contracts/external/openzeppelin-solidity/token/ERC20/ERC20.sol b/contracts/external/openzeppelin-solidity/token/ERC20/ERC20.sol index 9026f4f4d..79bd162df 100644 --- a/contracts/external/openzeppelin-solidity/token/ERC20/ERC20.sol +++ b/contracts/external/openzeppelin-solidity/token/ERC20/ERC20.sol @@ -1,70 +1,114 @@ -pragma solidity ^0.5.0; +pragma solidity 0.5.7; + import "./IERC20.sol"; import "../../math/SafeMath.sol"; +import "../../utils/Address.sol"; +import "../../utils/Context.sol"; + + /** - * @dev Implementation of the `IERC20` interface. + * @dev Implementation of the {IERC20} interface. * * This implementation is agnostic to the way tokens are created. This means - * that a supply mechanism has to be added in a derived contract using `_mint`. - * For a generic mechanism see `ERC20Mintable`. + * that a supply mechanism has to be added in a derived contract using {_mint}. + * For a generic mechanism see {ERC20PresetMinterPauser}. * - * *For a detailed writeup see our guide [How to implement supply - * mechanisms](https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226).* + * TIP: For a detailed writeup see our guide + * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How + * to implement supply mechanisms]. * * We have followed general OpenZeppelin guidelines: functions revert instead * of returning `false` on failure. This behavior is nonetheless conventional * and does not conflict with the expectations of ERC20 applications. * - * Additionally, an `Approval` event is emitted on calls to `transferFrom`. + * Additionally, an {Approval} event is emitted on calls to {transferFrom}. * This allows applications to reconstruct the allowance for all accounts just * by listening to said events. Other implementations of the EIP may not emit * these events, as it isn't required by the specification. * - * Finally, the non-standard `decreaseAllowance` and `increaseAllowance` + * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} * functions have been added to mitigate the well-known issues around setting - * allowances. See `IERC20.approve`. + * allowances. See {IERC20-approve}. */ -contract ERC20 is IERC20 { +contract ERC20 is Context, IERC20 { using SafeMath for uint256; + using Address for address; - mapping (address => uint256) internal _balances; + mapping (address => uint256) private _balances; mapping (address => mapping (address => uint256)) private _allowances; uint256 private _totalSupply; + string private _name; + string private _symbol; + uint8 private _decimals; + /** - * @dev Emitted when `value` tokens are moved from one account (`from`) to - * another (`to`). + * @dev Sets the values for {name} and {symbol}, initializes {decimals} with + * a default value of 18. + * + * To select a different value for {decimals}, use {_setupDecimals}. * - * Note that `value` may be zero. + * All three of these values are immutable: they can only be set once during + * construction. + */ + constructor (string memory name, string memory symbol) public { + _name = name; + _symbol = symbol; + _decimals = 18; + } + + /** + * @dev Returns the name of the token. + */ + function name() public view returns (string memory) { + return _name; + } + + /** + * @dev Returns the symbol of the token, usually a shorter version of the + * name. */ - event Transfer(address indexed from, address indexed to, uint256 value); + function symbol() public view returns (string memory) { + return _symbol; + } /** - * @dev Emitted when the allowance of a `spender` for an `owner` is set by - * a call to `approve`. `value` is the new allowance. + * @dev Returns the number of decimals used to get its user representation. + * For example, if `decimals` equals `2`, a balance of `505` tokens should + * be displayed to a user as `5,05` (`505 / 10 ** 2`). + * + * Tokens usually opt for a value of 18, imitating the relationship between + * Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is + * called. + * + * NOTE: This information is only used for _display_ purposes: it in + * no way affects any of the arithmetic of the contract, including + * {IERC20-balanceOf} and {IERC20-transfer}. */ - event Approval(address indexed owner, address indexed spender, uint256 value); + function decimals() public view returns (uint8) { + return _decimals; + } /** - * @dev See `IERC20.totalSupply`. + * @dev See {IERC20-totalSupply}. */ function totalSupply() public view returns (uint256) { return _totalSupply; } /** - * @dev See `IERC20.balanceOf`. + * @dev See {IERC20-balanceOf}. */ function balanceOf(address account) public view returns (uint256) { return _balances[account]; } /** - * @dev See `IERC20.transfer`. + * @dev See {IERC20-transfer}. * * Requirements: * @@ -72,71 +116,71 @@ contract ERC20 is IERC20 { * - the caller must have a balance of at least `amount`. */ function transfer(address recipient, uint256 amount) public returns (bool) { - _transfer(msg.sender, recipient, amount); + _transfer(_msgSender(), recipient, amount); return true; } /** - * @dev See `IERC20.allowance`. + * @dev See {IERC20-allowance}. */ function allowance(address owner, address spender) public view returns (uint256) { return _allowances[owner][spender]; } /** - * @dev See `IERC20.approve`. + * @dev See {IERC20-approve}. * * Requirements: * * - `spender` cannot be the zero address. */ - function approve(address spender, uint256 value) public returns (bool) { - _approve(msg.sender, spender, value); + function approve(address spender, uint256 amount) public returns (bool) { + _approve(_msgSender(), spender, amount); return true; } /** - * @dev See `IERC20.transferFrom`. + * @dev See {IERC20-transferFrom}. * - * Emits an `Approval` event indicating the updated allowance. This is not - * required by the EIP. See the note at the beginning of `ERC20`; + * Emits an {Approval} event indicating the updated allowance. This is not + * required by the EIP. See the note at the beginning of {ERC20}; * * Requirements: * - `sender` and `recipient` cannot be the zero address. - * - `sender` must have a balance of at least `value`. - * - the caller must have allowance for `sender`'s tokens of at least + * - `sender` must have a balance of at least `amount`. + * - the caller must have allowance for ``sender``'s tokens of at least * `amount`. */ function transferFrom(address sender, address recipient, uint256 amount) public returns (bool) { _transfer(sender, recipient, amount); - _approve(sender, msg.sender, _allowances[sender][msg.sender].sub(amount)); + _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance")); return true; } /** * @dev Atomically increases the allowance granted to `spender` by the caller. * - * This is an alternative to `approve` that can be used as a mitigation for - * problems described in `IERC20.approve`. + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. * - * Emits an `Approval` event indicating the updated allowance. + * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. */ function increaseAllowance(address spender, uint256 addedValue) public returns (bool) { - _approve(msg.sender, spender, _allowances[msg.sender][spender].add(addedValue)); + _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue)); return true; } /** * @dev Atomically decreases the allowance granted to `spender` by the caller. * - * This is an alternative to `approve` that can be used as a mitigation for - * problems described in `IERC20.approve`. + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. * - * Emits an `Approval` event indicating the updated allowance. + * Emits an {Approval} event indicating the updated allowance. * * Requirements: * @@ -145,17 +189,17 @@ contract ERC20 is IERC20 { * `subtractedValue`. */ function decreaseAllowance(address spender, uint256 subtractedValue) public returns (bool) { - _approve(msg.sender, spender, _allowances[msg.sender][spender].sub(subtractedValue)); + _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero")); return true; } /** * @dev Moves tokens `amount` from `sender` to `recipient`. * - * This is internal function is equivalent to `transfer`, and can be used to + * This is internal function is equivalent to {transfer}, and can be used to * e.g. implement automatic token fees, slashing mechanisms, etc. * - * Emits a `Transfer` event. + * Emits a {Transfer} event. * * Requirements: * @@ -167,32 +211,17 @@ contract ERC20 is IERC20 { require(sender != address(0), "ERC20: transfer from the zero address"); require(recipient != address(0), "ERC20: transfer to the zero address"); - _balances[sender] = _balances[sender].sub(amount); + _beforeTokenTransfer(sender, recipient, amount); + + _balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance"); _balances[recipient] = _balances[recipient].add(amount); emit Transfer(sender, recipient, amount); } - /** - * @dev Moves tokens `amount` from `sender` to `recipient`. - * - * Emits an `Approval` event indicating the updated allowance. This is not - * required by the EIP. See the note at the beginning of `ERC20`; - * - * Requirements: - * - `sender` and `recipient` cannot be the zero address. - * - `sender` must have a balance of at least `value`. - * - the caller must have allowance for `sender`'s tokens of at least - * `amount`. - */ - function _transferFrom(address sender, address recipient, uint256 amount) internal { - _transfer(sender, recipient, amount); - _approve(sender, msg.sender, _allowances[sender][msg.sender].sub(amount)); - } - /** @dev Creates `amount` tokens and assigns them to `account`, increasing * the total supply. * - * Emits a `Transfer` event with `from` set to the zero address. + * Emits a {Transfer} event with `from` set to the zero address. * * Requirements * @@ -201,28 +230,32 @@ contract ERC20 is IERC20 { function _mint(address account, uint256 amount) internal { require(account != address(0), "ERC20: mint to the zero address"); + _beforeTokenTransfer(address(0), account, amount); + _totalSupply = _totalSupply.add(amount); _balances[account] = _balances[account].add(amount); emit Transfer(address(0), account, amount); } - /** - * @dev Destoys `amount` tokens from `account`, reducing the + /** + * @dev Destroys `amount` tokens from `account`, reducing the * total supply. * - * Emits a `Transfer` event with `to` set to the zero address. + * Emits a {Transfer} event with `to` set to the zero address. * * Requirements * * - `account` cannot be the zero address. * - `account` must have at least `amount` tokens. */ - function _burn(address account, uint256 value) internal { + function _burn(address account, uint256 amount) internal { require(account != address(0), "ERC20: burn from the zero address"); - _totalSupply = _totalSupply.sub(value); - _balances[account] = _balances[account].sub(value); - emit Transfer(account, address(0), value); + _beforeTokenTransfer(account, address(0), amount); + + _balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance"); + _totalSupply = _totalSupply.sub(amount); + emit Transfer(account, address(0), amount); } /** @@ -231,29 +264,45 @@ contract ERC20 is IERC20 { * This is internal function is equivalent to `approve`, and can be used to * e.g. set automatic allowances for certain subsystems, etc. * - * Emits an `Approval` event. + * Emits an {Approval} event. * * Requirements: * * - `owner` cannot be the zero address. * - `spender` cannot be the zero address. */ - function _approve(address owner, address spender, uint256 value) internal { + function _approve(address owner, address spender, uint256 amount) internal { require(owner != address(0), "ERC20: approve from the zero address"); require(spender != address(0), "ERC20: approve to the zero address"); - _allowances[owner][spender] = value; - emit Approval(owner, spender, value); + _allowances[owner][spender] = amount; + emit Approval(owner, spender, amount); } /** - * @dev Destoys `amount` tokens from `account`.`amount` is then deducted - * from the caller's allowance. + * @dev Sets {decimals} to a value other than the default one of 18. * - * See `_burn` and `_approve`. + * WARNING: This function should only be called from the constructor. Most + * applications that interact with token contracts will not expect + * {decimals} to ever change, and may work incorrectly if it does. */ - function _burnFrom(address account, uint256 amount) internal { - _burn(account, amount); - _approve(account, msg.sender, _allowances[account][msg.sender].sub(amount)); + function _setupDecimals(uint8 decimals_) internal { + _decimals = decimals_; } -} + + /** + * @dev Hook that is called before any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * will be to transferred to `to`. + * - when `from` is zero, `amount` tokens will be minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens will be burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _beforeTokenTransfer(address from, address to, uint256 amount) internal { } +} \ No newline at end of file diff --git a/contracts/external/openzeppelin-solidity/utils/Context.sol b/contracts/external/openzeppelin-solidity/utils/Context.sol new file mode 100644 index 000000000..fb1614ba5 --- /dev/null +++ b/contracts/external/openzeppelin-solidity/utils/Context.sol @@ -0,0 +1,22 @@ +pragma solidity 0.5.7; + +/* + * @dev Provides information about the current execution context, including the + * sender of the transaction and its data. While these are generally available + * via msg.sender and msg.data, they should not be accessed in such a direct + * manner, since when dealing with GSN meta-transactions the account sending and + * paying for execution may not be the actual sender (as far as an application + * is concerned). + * + * This contract is only required for intermediate, library-like contracts. + */ +contract Context { + function _msgSender() internal view returns (address payable) { + return msg.sender; + } + + function _msgData() internal view returns (bytes memory) { + this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 + return msg.data; + } +} \ No newline at end of file diff --git a/contracts/external/openzeppelin-solidity/utils/EnumerableSet.sol b/contracts/external/openzeppelin-solidity/utils/EnumerableSet.sol new file mode 100644 index 000000000..4f2246dc1 --- /dev/null +++ b/contracts/external/openzeppelin-solidity/utils/EnumerableSet.sol @@ -0,0 +1,241 @@ +pragma solidity 0.5.7; + +/** + * @dev Library for managing + * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive + * types. + * + * Sets have the following properties: + * + * - Elements are added, removed, and checked for existence in constant time + * (O(1)). + * - Elements are enumerated in O(n). No guarantees are made on the ordering. + * + * ``` + * contract Example { + * // Add the library methods + * using EnumerableSet for EnumerableSet.AddressSet; + * + * // Declare a set state variable + * EnumerableSet.AddressSet private mySet; + * } + * ``` + * + * As of v3.0.0, only sets of type `address` (`AddressSet`) and `uint256` + * (`UintSet`) are supported. + */ +library EnumerableSet { + // To implement this library for multiple types with as little code + // repetition as possible, we write it in terms of a generic Set type with + // bytes32 values. + // The Set implementation uses private functions, and user-facing + // implementations (such as AddressSet) are just wrappers around the + // underlying Set. + // This means that we can only create new EnumerableSets for types that fit + // in bytes32. + + struct Set { + // Storage of set values + bytes32[] _values; + + // Position of the value in the `values` array, plus 1 because index 0 + // means a value is not in the set. + mapping (bytes32 => uint256) _indexes; + } + + /** + * @dev Add a value to a set. O(1). + * + * Returns true if the value was added to the set, that is if it was not + * already present. + */ + function _add(Set storage set, bytes32 value) private returns (bool) { + if (!_contains(set, value)) { + set._values.push(value); + // The value is stored at length-1, but we add 1 to all indexes + // and use 0 as a sentinel value + set._indexes[value] = set._values.length; + return true; + } else { + return false; + } + } + + /** + * @dev Removes a value from a set. O(1). + * + * Returns true if the value was removed from the set, that is if it was + * present. + */ + function _remove(Set storage set, bytes32 value) private returns (bool) { + // We read and store the value's index to prevent multiple reads from the same storage slot + uint256 valueIndex = set._indexes[value]; + + if (valueIndex != 0) { // Equivalent to contains(set, value) + // To delete an element from the _values array in O(1), we swap the element to delete with the last one in + // the array, and then remove the last element (sometimes called as 'swap and pop'). + // This modifies the order of the array, as noted in {at}. + + uint256 toDeleteIndex = valueIndex - 1; + uint256 lastIndex = set._values.length - 1; + + // When the value to delete is the last one, the swap operation is unnecessary. However, since this occurs + // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement. + + bytes32 lastvalue = set._values[lastIndex]; + + // Move the last value to the index where the value to delete is + set._values[toDeleteIndex] = lastvalue; + // Update the index for the moved value + set._indexes[lastvalue] = toDeleteIndex + 1; // All indexes are 1-based + + // Delete the slot where the moved value was stored + set._values.pop(); + + // Delete the index for the deleted slot + delete set._indexes[value]; + + return true; + } else { + return false; + } + } + + /** + * @dev Returns true if the value is in the set. O(1). + */ + function _contains(Set storage set, bytes32 value) private view returns (bool) { + return set._indexes[value] != 0; + } + + /** + * @dev Returns the number of values on the set. O(1). + */ + function _length(Set storage set) private view returns (uint256) { + return set._values.length; + } + + /** + * @dev Returns the value stored at position `index` in the set. O(1). + * + * Note that there are no guarantees on the ordering of values inside the + * array, and it may change when more values are added or removed. + * + * Requirements: + * + * - `index` must be strictly less than {length}. + */ + function _at(Set storage set, uint256 index) private view returns (bytes32) { + require(set._values.length > index, "EnumerableSet: index out of bounds"); + return set._values[index]; + } + + // AddressSet + + struct AddressSet { + Set _inner; + } + + /** + * @dev Add a value to a set. O(1). + * + * Returns true if the value was added to the set, that is if it was not + * already present. + */ + function add(AddressSet storage set, address value) internal returns (bool) { + return _add(set._inner, bytes32(uint256(value))); + } + + /** + * @dev Removes a value from a set. O(1). + * + * Returns true if the value was removed from the set, that is if it was + * present. + */ + function remove(AddressSet storage set, address value) internal returns (bool) { + return _remove(set._inner, bytes32(uint256(value))); + } + + /** + * @dev Returns true if the value is in the set. O(1). + */ + function contains(AddressSet storage set, address value) internal view returns (bool) { + return _contains(set._inner, bytes32(uint256(value))); + } + + /** + * @dev Returns the number of values in the set. O(1). + */ + function length(AddressSet storage set) internal view returns (uint256) { + return _length(set._inner); + } + + /** + * @dev Returns the value stored at position `index` in the set. O(1). + * + * Note that there are no guarantees on the ordering of values inside the + * array, and it may change when more values are added or removed. + * + * Requirements: + * + * - `index` must be strictly less than {length}. + */ + function at(AddressSet storage set, uint256 index) internal view returns (address) { + return address(uint256(_at(set._inner, index))); + } + + + // UintSet + + struct UintSet { + Set _inner; + } + + /** + * @dev Add a value to a set. O(1). + * + * Returns true if the value was added to the set, that is if it was not + * already present. + */ + function add(UintSet storage set, uint256 value) internal returns (bool) { + return _add(set._inner, bytes32(value)); + } + + /** + * @dev Removes a value from a set. O(1). + * + * Returns true if the value was removed from the set, that is if it was + * present. + */ + function remove(UintSet storage set, uint256 value) internal returns (bool) { + return _remove(set._inner, bytes32(value)); + } + + /** + * @dev Returns true if the value is in the set. O(1). + */ + function contains(UintSet storage set, uint256 value) internal view returns (bool) { + return _contains(set._inner, bytes32(value)); + } + + /** + * @dev Returns the number of values on the set. O(1). + */ + function length(UintSet storage set) internal view returns (uint256) { + return _length(set._inner); + } + + /** + * @dev Returns the value stored at position `index` in the set. O(1). + * + * Note that there are no guarantees on the ordering of values inside the + * array, and it may change when more values are added or removed. + * + * Requirements: + * + * - `index` must be strictly less than {length}. + */ + function at(UintSet storage set, uint256 index) internal view returns (uint256) { + return uint256(_at(set._inner, index)); + } +} \ No newline at end of file diff --git a/contracts/external/uniswap/FixedPoint.sol b/contracts/external/uniswap/FixedPoint.sol deleted file mode 100644 index 7c31de0af..000000000 --- a/contracts/external/uniswap/FixedPoint.sol +++ /dev/null @@ -1,105 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-or-later - -// computes square roots using the babylonian method -// https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method -pragma solidity >=0.5.0; -library Babylonian { - function sqrt(uint y) internal pure returns (uint z) { - if (y > 3) { - z = y; - uint x = y / 2 + 1; - while (x < z) { - z = x; - x = (y / x + x) / 2; - } - } else if (y != 0) { - z = 1; - } - // else z = 0 - } -} - -library UQ112x112 { - uint224 constant Q112 = 2**112; - - // encode a uint112 as a UQ112x112 - function encode(uint112 y) internal pure returns (uint224 z) { - z = uint224(y) * Q112; // never overflows - } - - // divide a UQ112x112 by a uint112, returning a UQ112x112 - function uqdiv(uint224 x, uint112 y) internal pure returns (uint224 z) { - z = x / uint224(y); - } -} - -// a library for handling binary fixed point numbers (https://en.wikipedia.org/wiki/Q_(number_format)) -library FixedPoint { - // range: [0, 2**112 - 1] - // resolution: 1 / 2**112 - struct uq112x112 { - uint224 _x; - } - - // range: [0, 2**144 - 1] - // resolution: 1 / 2**112 - struct uq144x112 { - uint _x; - } - - uint8 private constant RESOLUTION = 112; - uint private constant Q112 = uint(1) << RESOLUTION; - uint private constant Q224 = Q112 << RESOLUTION; - - // encode a uint112 as a UQ112x112 - function encode(uint112 x) internal pure returns (uq112x112 memory) { - return uq112x112(uint224(x) << RESOLUTION); - } - - // encodes a uint144 as a UQ144x112 - function encode144(uint144 x) internal pure returns (uq144x112 memory) { - return uq144x112(uint256(x) << RESOLUTION); - } - - // divide a UQ112x112 by a uint112, returning a UQ112x112 - function div(uq112x112 memory self, uint112 x) internal pure returns (uq112x112 memory) { - require(x != 0, 'FixedPoint: DIV_BY_ZERO'); - return uq112x112(self._x / uint224(x)); - } - - // multiply a UQ112x112 by a uint, returning a UQ144x112 - // reverts on overflow - function mul(uq112x112 memory self, uint y) internal pure returns (uq144x112 memory) { - uint z; - require(y == 0 || (z = uint(self._x) * y) / y == uint(self._x), "FixedPoint: MULTIPLICATION_OVERFLOW"); - return uq144x112(z); - } - - // returns a UQ112x112 which represents the ratio of the numerator to the denominator - // equivalent to encode(numerator).div(denominator) - function fraction(uint112 numerator, uint112 denominator) internal pure returns (uq112x112 memory) { - require(denominator > 0, "FixedPoint: DIV_BY_ZERO"); - return uq112x112((uint224(numerator) << RESOLUTION) / denominator); - } - - // decode a UQ112x112 into a uint112 by truncating after the radix point - function decode(uq112x112 memory self) internal pure returns (uint112) { - return uint112(self._x >> RESOLUTION); - } - - // decode a UQ144x112 into a uint144 by truncating after the radix point - function decode144(uq144x112 memory self) internal pure returns (uint144) { - return uint144(self._x >> RESOLUTION); - } - - // take the reciprocal of a UQ112x112 - function reciprocal(uq112x112 memory self) internal pure returns (uq112x112 memory) { - require(self._x != 0, 'FixedPoint: ZERO_RECIPROCAL'); - return uq112x112(uint224(Q224 / self._x)); - } - - // square root of a UQ112x112 - function sqrt(uq112x112 memory self) internal pure returns (uq112x112 memory) { - return uq112x112(uint224(Babylonian.sqrt(uint256(self._x)) << 56)); - } -} diff --git a/contracts/external/uniswap/oracleLibrary.sol b/contracts/external/uniswap/oracleLibrary.sol deleted file mode 100644 index 8e3ad2c4b..000000000 --- a/contracts/external/uniswap/oracleLibrary.sol +++ /dev/null @@ -1,35 +0,0 @@ -pragma solidity >=0.5.0; - -import './solidity-interface.sol'; -import './FixedPoint.sol'; - -// library with helper methods for oracles that are concerned with computing average prices -library UniswapV2OracleLibrary { - using FixedPoint for *; - - // helper function that returns the current block timestamp within the range of uint32, i.e. [0, 2**32 - 1] - function currentBlockTimestamp() internal view returns (uint32) { - return uint32(block.timestamp % 2 ** 32); - } - - // produces the cumulative price using counterfactuals to save gas and avoid a call to sync. - function currentCumulativePrices( - address pair - ) internal view returns (uint price0Cumulative, uint price1Cumulative, uint32 blockTimestamp) { - blockTimestamp = currentBlockTimestamp(); - price0Cumulative = IUniswapV2Pair(pair).price0CumulativeLast(); - price1Cumulative = IUniswapV2Pair(pair).price1CumulativeLast(); - - // if time has elapsed since the last update on the pair, mock the accumulated price values - (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast) = IUniswapV2Pair(pair).getReserves(); - if (blockTimestampLast != blockTimestamp) { - // subtraction overflow is desired - uint32 timeElapsed = blockTimestamp - blockTimestampLast; - // addition overflow is desired - // counterfactual - price0Cumulative += uint(FixedPoint.fraction(reserve1, reserve0)._x) * timeElapsed; - // counterfactual - price1Cumulative += uint(FixedPoint.fraction(reserve0, reserve1)._x) * timeElapsed; - } - } -} diff --git a/contracts/external/uniswap/solidity-interface.sol b/contracts/external/uniswap/solidity-interface.sol deleted file mode 100644 index d9ba5b252..000000000 --- a/contracts/external/uniswap/solidity-interface.sol +++ /dev/null @@ -1,105 +0,0 @@ -pragma solidity >=0.5.0; - -interface IUniswapV2Factory { - event PairCreated(address indexed token0, address indexed token1, address pair, uint); - - function getPair(address tokenA, address tokenB) external view returns (address pair); - function allPairs(uint) external view returns (address pair); - function allPairsLength() external view returns (uint); - - function feeTo() external view returns (address); - function feeToSetter() external view returns (address); - - function createPair(address tokenA, address tokenB) external returns (address pair); -} - -interface IUniswapV2Router02 { - function factory() external pure returns (address); - - function WETH() external pure returns (address); - - function swapExactETHForTokens(uint amountOutMin, address[] calldata path, address to, uint deadline) - external - payable - returns (uint[] memory amounts); - function getAmountsOut(uint amountIn, address[] calldata path) external view returns (uint[] memory amounts); - -} - -interface IUniswapV2Pair { - event Approval(address indexed owner, address indexed spender, uint value); - event Transfer(address indexed from, address indexed to, uint value); - - function name() external pure returns (string memory); - function symbol() external pure returns (string memory); - function decimals() external pure returns (uint8); - function totalSupply() external view returns (uint); - function balanceOf(address owner) external view returns (uint); - function allowance(address owner, address spender) external view returns (uint); - - function approve(address spender, uint value) external returns (bool); - function transfer(address to, uint value) external returns (bool); - function transferFrom(address from, address to, uint value) external returns (bool); - - function DOMAIN_SEPARATOR() external view returns (bytes32); - function PERMIT_TYPEHASH() external pure returns (bytes32); - function nonces(address owner) external view returns (uint); - - function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external; - - event Mint(address indexed sender, uint amount0, uint amount1); - event Burn(address indexed sender, uint amount0, uint amount1, address indexed to); - event Swap( - address indexed sender, - uint amount0In, - uint amount1In, - uint amount0Out, - uint amount1Out, - address indexed to - ); - event Sync(uint112 reserve0, uint112 reserve1); - - function MINIMUM_LIQUIDITY() external pure returns (uint); - function factory() external view returns (address); - function token0() external view returns (address); - function token1() external view returns (address); - function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast); - function price0CumulativeLast() external view returns (uint); - function price1CumulativeLast() external view returns (uint); - function kLast() external view returns (uint); - - function mint(address to) external returns (uint liquidity); - function burn(address to) external returns (uint amount0, uint amount1); - function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external; - function skim(address to) external; - function sync() external; - - function initialize(address, address) external; -} - -interface IUniswapV2ERC20 { - event Approval(address indexed owner, address indexed spender, uint value); - event Transfer(address indexed from, address indexed to, uint value); - - function name() external pure returns (string memory); - function symbol() external pure returns (string memory); - function decimals() external pure returns (uint8); - function totalSupply() external view returns (uint); - function balanceOf(address owner) external view returns (uint); - function allowance(address owner, address spender) external view returns (uint); - - function approve(address spender, uint value) external returns (bool); - function transfer(address to, uint value) external returns (bool); - function transferFrom(address from, address to, uint value) external returns (bool); - - function DOMAIN_SEPARATOR() external view returns (bytes32); - function PERMIT_TYPEHASH() external pure returns (bytes32); - function nonces(address owner) external view returns (uint); - - function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external; -} - - -interface IUniswapV2Callee { - function uniswapV2Call(address sender, uint amount0, uint amount1, bytes calldata data) external; -} diff --git a/contracts/interfaces/IAllMarkets.sol b/contracts/interfaces/IAllMarkets.sol new file mode 100644 index 000000000..626bd523e --- /dev/null +++ b/contracts/interfaces/IAllMarkets.sol @@ -0,0 +1,27 @@ +pragma solidity 0.5.7; + +contract IAllMarkets { + + enum PredictionStatus { + Live, + InSettlement, + Cooling, + InDispute, + Settled + } + + function marketStatus(uint256 _marketId) public view returns(PredictionStatus); + + function burnDisputedProposalTokens(uint _proposaId) external; + + function getTotalStakedValueInPLOT(uint256 _marketId) public view returns(uint256); + + function getTotalStakedWorthInPLOT(uint256 _marketId) public view returns(uint256 _tokenStakedWorth); + + function getMarketCurrencyData(bytes32 currencyType) external view returns(address); + + function getMarketOptionPricingParams(uint _marketId, uint _option) public view returns(uint[] memory,uint32,address); + + function getMarketData(uint256 _marketId) external view returns + (bytes32 _marketCurrency,uint neutralMinValue,uint neutralMaxValue, uint[] memory _tokenStaked,uint _predictionTime,uint _expireTime, PredictionStatus _predictionStatus); +} diff --git a/contracts/interfaces/IMarketCreationRewards.sol b/contracts/interfaces/IMarketCreationRewards.sol new file mode 100644 index 000000000..4714857f1 --- /dev/null +++ b/contracts/interfaces/IMarketCreationRewards.sol @@ -0,0 +1,16 @@ +pragma solidity 0.5.7; + +contract IMarketCreationRewards { + + function calculateMarketCreationIncentive(address _createdBy, uint64 _marketId) external; + + // function depositMarketRewardPoolShare(uint256 _marketId, uint256 _plotShare, uint64 _plotDeposit) external payable; + function depositMarketCreationReward(uint256 _marketId, uint256 _plotShare) external payable; + + function returnMarketRewardPoolShare(uint256 _marketId) external; + + function getMarketCreatorRPoolShareParams(uint256 _market, uint256 plotStaked) external view returns(uint16, bool); + + function transferAssets(address _asset, address _to, uint _amount) external; + +} diff --git a/contracts/interfaces/IMarketUtility.sol b/contracts/interfaces/IMarketUtility.sol index 9f2e76196..eef451a27 100644 --- a/contracts/interfaces/IMarketUtility.sol +++ b/contracts/interfaces/IMarketUtility.sol @@ -1,7 +1,9 @@ pragma solidity 0.5.7; contract IMarketUtility { - function initialize(address payable[] calldata _addressParams, address _initiater) external; + function initialize(address _initiater) external; + + mapping(address => uint256) public conversionRate; /** * @dev to Set authorized address to update parameters @@ -28,7 +30,23 @@ contract IMarketUtility { **/ function getMarketInitialParams() public view returns(address[] memory, uint , uint, uint, uint); - function getAssetPriceUSD(address _currencyAddress) external view returns(uint latestAnswer); + function getAssetPriceUSD( + address _currencyFeedAddress, + bytes32 _marketCurr + ) public view returns (uint256 latestAnswer); + + function getAssetValueETH(address _currencyAddress, uint256 _amount) + public + view + returns (uint256 tokenEthValue); + + function checkMultiplier(address _asset, address _user, uint _predictionStake, uint predictionPoints, uint _stakeValue) public view returns(uint, bool); + + function calculatePredictionPoints(uint _marketId, uint _prediction, address _user, bool multiplierApplied, uint _predictionStake) external view returns(uint64 predictionPoints, bool isMultiplierApplied); + + function calculateOptionRange(uint _optionRangePerc, uint64 _decimals, uint8 _roundOfToNearest, address _marketFeed, bytes32 _marketCurr) external view returns(uint64 _minValue, uint64 _maxValue); + + function getOptionPrice(uint256 _marketId, uint _prediction) public view returns(uint64 _optionPrice); function getPriceFeedDecimals(address _priceFeed) public view returns(uint8); @@ -41,6 +59,8 @@ contract IMarketUtility { function calculatePredictionValue(uint[] memory params, address asset, address user, address marketFeedAddress, bool _checkMultiplier) public view returns(uint _predictionValue, bool _multiplierApplied); + function isAuthorized(address _address) external view returns(bool); + /** * @dev Get basic market details * @return Minimum amount required to predict in market @@ -51,7 +71,6 @@ contract IMarketUtility { public view returns ( - uint256, uint256, uint256, uint256 @@ -69,4 +88,18 @@ contract IMarketUtility { address _currencyFeedAddress, uint256 _settleTime ) public view returns (uint256 latestAnswer, uint256 roundId); + + + function stakingFactorMinStake() external view returns(uint); + function stakingFactorWeightage() external view returns(uint); + function currentPriceWeightage() external view returns(uint32); + + function getPriceCalculationParams() + public + view + returns ( + uint256, + uint32, + uint32 + ); } diff --git a/contracts/interfaces/IToken.sol b/contracts/interfaces/IToken.sol index a9a57f303..6fa949089 100644 --- a/contracts/interfaces/IToken.sol +++ b/contracts/interfaces/IToken.sol @@ -61,4 +61,9 @@ contract IToken { */ function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); + function lockForGovernanceVote(address _of, uint256 _period) public; + + function isLockedForGV(address _of) public view returns (bool); + + function changeOperator(address _newOperator) public returns (bool); } diff --git a/contracts/marketImplementations/MarketBTC.sol b/contracts/marketImplementations/MarketBTC.sol deleted file mode 100644 index 2b3237502..000000000 --- a/contracts/marketImplementations/MarketBTC.sol +++ /dev/null @@ -1,10 +0,0 @@ -pragma solidity 0.5.7; - -import "../Market.sol"; -contract MarketBTC is Market { - - bool constant isChainlinkFeed = true; - address constant marketFeedAddress = 0x5e2aa6b66531142bEAB830c385646F97fa03D80a; - bytes32 public constant marketCurrency = "BTC/USDT"; - -} diff --git a/contracts/mock/DummyMockMarket.sol b/contracts/mock/DummyMockMarket.sol deleted file mode 100644 index 16100b6ec..000000000 --- a/contracts/mock/DummyMockMarket.sol +++ /dev/null @@ -1,28 +0,0 @@ -pragma solidity 0.5.7; - -import "../Market.sol"; - -contract DummyMockMarket is Market { - - mapping(uint => uint) optionPrices; - - bool public mockFlag; - - function setMockPriceFlag(bool _flag) public { - mockFlag = _flag; - } - - function dummyFunction() public view returns(uint) - { - - return 123; - } - - /** - * @dev Calculate the result of market. - * @param _value The current price of market currency. - */ - function calculatePredictionResult(uint _value) public { - _postResult(_value, 0); - } -} \ No newline at end of file diff --git a/contracts/mock/DummyTokenMock.sol b/contracts/mock/DummyTokenMock.sol index f4565c0d4..43b8e1d22 100644 --- a/contracts/mock/DummyTokenMock.sol +++ b/contracts/mock/DummyTokenMock.sol @@ -5,17 +5,15 @@ import "../external/openzeppelin-solidity/token/ERC20/ERC20.sol"; // To branch coverage of token transer contract DummyTokenMock is ERC20 { - string public name; - string public symbol; - uint8 public decimals = 18; + // string public name; + // string public symbol; + // uint8 public decimals = 18; mapping(address=>bool) _dummyBit; bool public retBit; - constructor(string memory tokenName, string memory tokenSymbol) public { - name = tokenName; - symbol = tokenSymbol; + constructor(string memory tokenName, string memory tokenSymbol) public ERC20(tokenName,tokenSymbol){ } function mint(uint256 amount) public returns (uint256) { @@ -37,16 +35,6 @@ contract DummyTokenMock is ERC20 { return true; } - /** - * @dev Burns a specific amount of tokens from the target address and decrements allowance - * @param from address The address which you want to send tokens from - * @param value uint256 The amount of token to be burned - */ - function burnFrom(address from, uint256 value) public returns (bool) { - _burnFrom(from, value); - return true; - } - /** * @dev Transfer token for a specified address * @param to The address to transfer to. @@ -82,7 +70,7 @@ contract DummyTokenMock is ERC20 { * @return An uint256 representing the amount owned by the passed address. */ function balanceOf(address owner) public view returns (uint256) { - return _balances[owner]; + return super.balanceOf(owner); } /** diff --git a/contracts/mock/DummyTokenMock2.sol b/contracts/mock/DummyTokenMock2.sol new file mode 100644 index 000000000..f22cd69c0 --- /dev/null +++ b/contracts/mock/DummyTokenMock2.sol @@ -0,0 +1,89 @@ +pragma solidity 0.5.7; + +import "../external/openzeppelin-solidity/token/ERC20/ERC20.sol"; + +contract SampleERC is ERC20 { + + // string public name; + // string public symbol; + // uint8 public decimals = 18; + + constructor(string memory tokenName, string memory tokenSymbol) public ERC20(tokenName,tokenSymbol) { + + } + + function mint(uint256 amount) public returns (uint256) { + _mint(msg.sender, amount); + return 0; + } + + /** + * @dev burns an amount of the tokens of the message sender + * account. + * @param amount The amount that will be burnt. + */ + function burn(uint256 amount) public returns (bool) { + _burn(msg.sender, amount); + return true; + } + + // * + // * @dev Burns a specific amount of tokens from the target address and decrements allowance + // * @param from address The address which you want to send tokens from + // * @param value uint256 The amount of token to be burned + + // function burnFrom(address from, uint256 value) public returns (bool) { + // _burnFrom(from, value); + // return true; + // } + + /** + * @dev Transfer token for a specified address + * @param to The address to transfer to. + * @param value The amount to be transferred. + */ + function transfer(address to, uint256 value) public returns (bool) { + + _transfer(msg.sender, to, value); + return true; + } + + /** + * @dev Transfer tokens from one address to another + * @param from address The address which you want to send tokens from + * @param to address The address which you want to transfer to + * @param value uint256 the amount of tokens to be transferred + */ + function transferFrom( + address from, + address to, + uint256 value + ) + public + returns (bool) + { + super.transferFrom(from, to, value); + return true; + } + + /** + * @dev Gets the balance of the specified address. + * @param owner The address to query the balance of. + * @return An uint256 representing the amount owned by the passed address. + */ + function balanceOf(address owner) public view returns (uint256) { + return super.balanceOf(owner); + } + + /** + * @dev function that mints an amount of the token and assigns it to + * an account. + * @param account The account that will receive the created tokens. + * @param amount The amount that will be created. + */ + function mint(address account, uint256 amount) public returns(bool) { + _mint(account, amount); + return true; + } + +} diff --git a/contracts/mock/MockAllMarkets.sol b/contracts/mock/MockAllMarkets.sol new file mode 100644 index 000000000..937d9673b --- /dev/null +++ b/contracts/mock/MockAllMarkets.sol @@ -0,0 +1,11 @@ +pragma solidity 0.5.7; + +import "../AllMarkets.sol"; + +contract MockAllMarkets is AllMarkets { + + function postResultMock(uint _val, uint _marketId) external { + _postResult(_val, 0 , _marketId); + } + +} \ No newline at end of file diff --git a/contracts/mock/MockBTCMarket.sol b/contracts/mock/MockBTCMarket.sol deleted file mode 100644 index e16b17345..000000000 --- a/contracts/mock/MockBTCMarket.sol +++ /dev/null @@ -1,43 +0,0 @@ -pragma solidity 0.5.7; - -import "../marketImplementations/MarketBTC.sol"; - -contract MockBTCMarket is MarketBTC { - - mapping(uint => uint) optionPrices; - - bool public mockFlag; - - function setMockPriceFlag(bool _flag) public { - mockFlag = _flag; - } - - function setOptionRangesPublic(uint _midRangeMin, uint _midRangeMax) public{ - marketData.neutralMinValue = uint64(_midRangeMin*1e8); - marketData.neutralMaxValue = uint64(_midRangeMax*1e8); - // optionsAvailable[1].minValue = 0; - // optionsAvailable[1].maxValue = _midRangeMin.sub(1); - // optionsAvailable[2].minValue = _midRangeMin; - // optionsAvailable[2].maxValue = _midRangeMax; - // optionsAvailable[3].minValue = _midRangeMax.add(1); - // optionsAvailable[3].maxValue = ~uint256(0) ; - } - - function initiate(uint64 _startTime, uint64 _predictionTime, uint64 _minValue, uint64 _maxValue) public payable { - mockFlag = true; - super.initiate(_startTime, _predictionTime, _minValue, _maxValue); - } - - /** - * @dev Calculate the result of market. - * @param _value The current price of market currency. - */ - function calculatePredictionResult(uint _value) public { - _postResult(_value, 0); - } - - function setOptionPrice(uint _option, uint _price) public { - optionPrices[_option] = _price; - } - -} \ No newline at end of file diff --git a/contracts/mock/MockChainLinkGasPriceAgg.sol b/contracts/mock/MockChainLinkGasPriceAgg.sol new file mode 100644 index 000000000..a9b2c3c8d --- /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 diff --git a/contracts/mock/MockConfig.sol b/contracts/mock/MockConfig.sol index f068d967e..4cd12a651 100644 --- a/contracts/mock/MockConfig.sol +++ b/contracts/mock/MockConfig.sol @@ -8,15 +8,16 @@ contract MockConfig is MarketUtility { bool public mockFlag; mapping(uint => uint) optionPrices; - function initialize(address payable[] memory _addressParams, address _intiater) public { + function initialize(address _intiater) public { priceOfToken = 1e16; mockFlag = true; - super.initialize(_addressParams, _intiater); + nextOptionPrice = 10; + super.initialize(_intiater); } - function setWeth(address _weth) external { - weth = _weth; - } + // function setWeth(address _weth) external { + // weth = _weth; + // } function setPrice(uint _newPrice) external { priceOfToken = _newPrice; @@ -26,16 +27,16 @@ contract MockConfig is MarketUtility { return amountIn.mul(priceOfToken).div(1e18); } - function getValueAndMultiplierParameters(address _asset, uint _amount) public view returns(uint, uint) { - uint _value = _amount; - if(_asset == ETH_ADDRESS) { - // address pair = uniswapFactory.getPair(plotToken, weth); - _value = _amount.mul(1e18).div(priceOfToken); - // uint[] memory output = uniswapRouter.getAmountsOut(_amount, uniswapEthToTokenPath); - // _value = output[1]; - } - return (minStakeForMultiplier, _value); - } + // function getValueAndMultiplierParameters(address _asset, uint _amount) public view returns(uint, uint) { + // uint _value = _amount; + // if(_asset == ETH_ADDRESS) { + // // address pair = uniswapFactory.getPair(plotToken, weth); + // _value = _amount.mul(1e18).div(priceOfToken); + // // uint[] memory output = uniswapRouter.getAmountsOut(_amount, uniswapEthToTokenPath); + // // _value = output[1]; + // } + // return (minStakeForMultiplier, _value); + // } /** * @dev Internal function to update pair cummulative price @@ -43,9 +44,9 @@ contract MockConfig is MarketUtility { function _setCummulativePrice() internal { } - function update() external { + // function update() external { - } + // } function setOptionPrice(uint _option, uint _price) public { optionPrices[_option] = _price; @@ -59,6 +60,25 @@ contract MockConfig is MarketUtility { if(mockFlag) { return optionPrices[params[0]]; } - return super.calculateOptionPrice(params, marketFeedAddress); + // return super.calculateOptionPrice(params, marketFeedAddress); + } + + uint64 public nextOptionPrice; + + function setNextOptionPrice(uint64 _price) public { + nextOptionPrice = _price; + } + + function getOptionPrice(uint _marketId, uint256 _prediction) public view returns(uint64 _optionPrice) { + if(mockFlag) { + return nextOptionPrice; + } + else { + return super.getOptionPrice(_marketId, _prediction); + } + } + + function setMaxPredictionValue(uint256 _maxPredictionAmount) public { + maxPredictionAmount = _maxPredictionAmount; } } \ No newline at end of file diff --git a/contracts/mock/MockMarket.sol b/contracts/mock/MockMarket.sol deleted file mode 100644 index a5ec550f1..000000000 --- a/contracts/mock/MockMarket.sol +++ /dev/null @@ -1,43 +0,0 @@ -pragma solidity 0.5.7; - -import "../Market.sol"; - -contract MockMarket is Market { - - mapping(uint => uint) optionPrices; - - bool public mockFlag; - - function setMockPriceFlag(bool _flag) public { - mockFlag = _flag; - } - - function setOptionRangesPublic(uint _midRangeMin, uint _midRangeMax) public{ - marketData.neutralMinValue = uint64(_midRangeMin*1e8); - marketData.neutralMaxValue = uint64(_midRangeMax*1e8); - // optionsAvailable[1].minValue = 0; - // optionsAvailable[1].maxValue = _midRangeMin.sub(1); - // optionsAvailable[2].minValue = _midRangeMin; - // optionsAvailable[2].maxValue = _midRangeMax; - // optionsAvailable[3].minValue = _midRangeMax.add(1); - // optionsAvailable[3].maxValue = ~uint256(0) ; - } - - function initiate(uint64 _startTime, uint64 _predictionTime, uint64 _minValue, uint64 _maxValue) public payable { - mockFlag = true; - super.initiate(_startTime, _predictionTime, _minValue, _maxValue); - } - - /** - * @dev Calculate the result of market. - * @param _value The current price of market currency. - */ - function calculatePredictionResult(uint _value) public { - _postResult(_value, 0); - } - - function setOptionPrice(uint _option, uint _price) public { - optionPrices[_option] = _price; - } - -} \ No newline at end of file diff --git a/contracts/mock/MockMarketRegistry.sol b/contracts/mock/MockMarketRegistry.sol deleted file mode 100644 index bc6ccd215..000000000 --- a/contracts/mock/MockMarketRegistry.sol +++ /dev/null @@ -1,10 +0,0 @@ -pragma solidity 0.5.7; - -import "../MarketRegistry.sol"; - -contract MockMarketRegistry is MarketRegistry { - - function transferPlot(address payable _to, uint _amount) external { - _transferAsset(address(plotToken), _to, _amount); - } -} \ No newline at end of file diff --git a/contracts/mock/MockPLOT.sol b/contracts/mock/MockPLOT.sol index bc9856e3d..8d233b044 100644 --- a/contracts/mock/MockPLOT.sol +++ b/contracts/mock/MockPLOT.sol @@ -3,10 +3,22 @@ import "../PlotXToken.sol"; contract MockPLOT is PlotXToken { - constructor(uint256 initialSupply, address owner) public PlotXToken(initialSupply, owner) { + constructor(string memory name_, + string memory symbol_, + uint8 decimals_, + address _operator, + address childChainManager) public PlotXToken(name_,symbol_,decimals_,_operator,childChainManager) { + } + + function mint(address user, uint amount) public returns(bool) { + _mint(user,amount); } function burnTokens(address _of, uint _amount) external { _burn(_of, _amount); } + + function burn(uint _amount) external { + _burn(msg.sender, _amount); + } } \ No newline at end of file diff --git a/contracts/mock/MockTokenController.sol b/contracts/mock/MockTokenController.sol index 2c6d10c86..0fbd3c5b0 100644 --- a/contracts/mock/MockTokenController.sol +++ b/contracts/mock/MockTokenController.sol @@ -5,7 +5,7 @@ import "../TokenController.sol"; contract MockTokenController is TokenController { uint public bit; - + /** * @dev to change the operator address * @param _newOperator is the new address of operator diff --git a/contracts/mock/MockUniswapFactory.sol b/contracts/mock/MockUniswapFactory.sol deleted file mode 100644 index 37dbd5f41..000000000 --- a/contracts/mock/MockUniswapFactory.sol +++ /dev/null @@ -1,14 +0,0 @@ -pragma solidity 0.5.7; - - -contract MockUniswapFactory { - - address public plotETHPair; - function getPair(address tokenA, address tokenB) external view returns (address pair) { - return plotETHPair; - } - - function setPair(address _plotETHPair) public { - plotETHPair = _plotETHPair; - } -} diff --git a/contracts/mock/MockUniswapPair.sol b/contracts/mock/MockUniswapPair.sol deleted file mode 100644 index 0ca4b96e4..000000000 --- a/contracts/mock/MockUniswapPair.sol +++ /dev/null @@ -1,13 +0,0 @@ -pragma solidity 0.5.7; - - -contract MockUniswapPair { - - address public token0; - address public token1; - constructor(address _token0, address _token1) public { - token0 = _token0; - token1 = _token1; - } - -} diff --git a/contracts/mock/MockUniswapRouter.sol b/contracts/mock/MockUniswapRouter.sol deleted file mode 100644 index 3d4aca49f..000000000 --- a/contracts/mock/MockUniswapRouter.sol +++ /dev/null @@ -1,54 +0,0 @@ -pragma solidity 0.5.7; - -import "../external/uniswap/solidity-interface.sol"; -import "../external/openzeppelin-solidity/math/SafeMath.sol"; -import "../interfaces/IToken.sol"; - -contract MockUniswapRouter { - - using SafeMath for uint; - - uint public priceOfToken = 1e16; - address token; - - constructor(address _token) public { - token = _token; - } - - function WETH() external pure returns (address) { - return 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE; - } - - function setPrice(uint _newPrice) external { - priceOfToken = _newPrice; - } - - - function swapExactETHForTokens(uint amountOutMin, address[] calldata path, address to, uint deadline) - external - payable - returns (uint[] memory amounts) { - uint ethSent = msg.value; - uint tokenOutput = ethSent.mul(1e18).div(priceOfToken); - IToken(token).transfer(to, tokenOutput); - amounts = new uint[](2); - amounts[0] = ethSent; - amounts[1] = tokenOutput; - } - - function getAmountsOut(uint amountIn, address[] calldata path) external view returns (uint[] memory amounts) { - amounts = new uint[](2); - amounts[0] = amountIn; - if(path[0] == 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) { - amounts[1] = amountIn.mul(1e18).div(priceOfToken); - } else { - amounts[1] = amountIn.mul(priceOfToken).div(1e18); - } - } - - function () payable external { - - } - - -} \ No newline at end of file diff --git a/contracts/mock/MockUniswapV2Pair.sol b/contracts/mock/MockUniswapV2Pair.sol deleted file mode 100644 index 6cde2eb1d..000000000 --- a/contracts/mock/MockUniswapV2Pair.sol +++ /dev/null @@ -1,299 +0,0 @@ -pragma solidity 0.5.7; - -import '../external/openzeppelin-solidity/math/Math.sol'; -import '../external/openzeppelin-solidity/math/SafeMath.sol'; -import '../external/uniswap/FixedPoint.sol'; -import '../external/uniswap/solidity-interface.sol'; -import '../interfaces/IToken.sol'; - - -contract UniswapV2ERC20 is IUniswapV2ERC20 { - using SafeMath for uint; - - string public constant name = 'Uniswap V2'; - string public constant symbol = 'UNI-V2'; - uint8 public constant decimals = 18; - uint public totalSupply; - mapping(address => uint) public balanceOf; - mapping(address => mapping(address => uint)) public allowance; - - bytes32 public DOMAIN_SEPARATOR; - // keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"); - bytes32 public constant PERMIT_TYPEHASH = 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9; - mapping(address => uint) public nonces; - - event Approval(address indexed owner, address indexed spender, uint value); - event Transfer(address indexed from, address indexed to, uint value); - - constructor() public { - uint chainId; - assembly { - chainId := 1 - } - DOMAIN_SEPARATOR = keccak256( - abi.encode( - keccak256('EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)'), - keccak256(bytes(name)), - keccak256(bytes('1')), - chainId, - address(this) - ) - ); - } - - function _mint(address to, uint value) internal { - totalSupply = totalSupply.add(value); - balanceOf[to] = balanceOf[to].add(value); - emit Transfer(address(0), to, value); - } - - function _burn(address from, uint value) internal { - balanceOf[from] = balanceOf[from].sub(value); - totalSupply = totalSupply.sub(value); - emit Transfer(from, address(0), value); - } - - function _approve(address owner, address spender, uint value) private { - allowance[owner][spender] = value; - emit Approval(owner, spender, value); - } - - function _transfer(address from, address to, uint value) private { - balanceOf[from] = balanceOf[from].sub(value); - balanceOf[to] = balanceOf[to].add(value); - emit Transfer(from, to, value); - } - - function approve(address spender, uint value) external returns (bool) { - _approve(msg.sender, spender, value); - return true; - } - - function transfer(address to, uint value) external returns (bool) { - _transfer(msg.sender, to, value); - return true; - } - - function transferFrom(address from, address to, uint value) external returns (bool) { - if (allowance[from][msg.sender] != uint(-1)) { - allowance[from][msg.sender] = allowance[from][msg.sender].sub(value); - } - _transfer(from, to, value); - return true; - } - - function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external { - require(deadline >= block.timestamp, 'UniswapV2: EXPIRED'); - bytes32 digest = keccak256( - abi.encodePacked( - '\x19\x01', - DOMAIN_SEPARATOR, - keccak256(abi.encode(PERMIT_TYPEHASH, owner, spender, value, nonces[owner]++, deadline)) - ) - ); - address recoveredAddress = ecrecover(digest, v, r, s); - require(recoveredAddress != address(0) && recoveredAddress == owner, 'UniswapV2: INVALID_SIGNATURE'); - _approve(owner, spender, value); - } -} - -contract MockUniswapV2Pair is IUniswapV2Pair, UniswapV2ERC20 { - using SafeMath for uint; - using UQ112x112 for uint224; - - uint public constant MINIMUM_LIQUIDITY = 10**3; - bytes4 private constant SELECTOR = bytes4(keccak256(bytes('transfer(address,uint256)'))); - - address public factory; - address public token0; - address public token1; - - uint112 private reserve0; // uses single storage slot, accessible via getReserves - uint112 private reserve1; // uses single storage slot, accessible via getReserves - uint32 private blockTimestampLast; // uses single storage slot, accessible via getReserves - - uint public price0CumulativeLast; - uint public price1CumulativeLast; - uint public kLast; // reserve0 * reserve1, as of immediately after the most recent liquidity event - - uint private unlocked = 1; - modifier lock() { - require(unlocked == 1, 'UniswapV2: LOCKED'); - unlocked = 0; - _; - unlocked = 1; - } - - function getReserves() public view returns (uint112 _reserve0, uint112 _reserve1, uint32 _blockTimestampLast) { - _reserve0 = reserve0; - _reserve1 = reserve1; - _blockTimestampLast = blockTimestampLast; - } - - function _safeTransfer(address token, address to, uint value) private { - (bool success, bytes memory data) = token.call(abi.encodeWithSelector(SELECTOR, to, value)); - require(success && (data.length == 0 || abi.decode(data, (bool))), 'UniswapV2: TRANSFER_FAILED'); - } - - event Mint(address indexed sender, uint amount0, uint amount1); - event Burn(address indexed sender, uint amount0, uint amount1, address indexed to); - event Swap( - address indexed sender, - uint amount0In, - uint amount1In, - uint amount0Out, - uint amount1Out, - address indexed to - ); - event Sync(uint112 reserve0, uint112 reserve1); - - constructor() public { - factory = msg.sender; - } - - // called once by the factory at time of deployment - function initialize(address _token0, address _token1) external { - require(msg.sender == factory, 'UniswapV2: FORBIDDEN'); // sufficient check - token0 = _token0; - token1 = _token1; - } - - // update reserves and, on the first call per block, price accumulators - function _update(uint balance0, uint balance1, uint112 _reserve0, uint112 _reserve1) private { - require(balance0 <= uint112(-1) && balance1 <= uint112(-1), 'UniswapV2: OVERFLOW'); - uint32 blockTimestamp = uint32(block.timestamp % 2**32); - uint32 timeElapsed = blockTimestamp - blockTimestampLast; // overflow is desired - if (timeElapsed > 0 && _reserve0 != 0 && _reserve1 != 0) { - // * never overflows, and + overflow is desired - price0CumulativeLast += uint(UQ112x112.encode(_reserve1).uqdiv(_reserve0)) * timeElapsed; - price1CumulativeLast += uint(UQ112x112.encode(_reserve0).uqdiv(_reserve1)) * timeElapsed; - } - reserve0 = uint112(balance0); - reserve1 = uint112(balance1); - blockTimestampLast = blockTimestamp; - emit Sync(reserve0, reserve1); - } - - function sqrt(uint x) internal pure returns (uint y) { - uint z = (x + 1) / 2; - y = x; - while (z < y) { - y = z; - z = (x / z + z) / 2; - } - } - - // if fee is on, mint liquidity equivalent to 1/6th of the growth in sqrt(k) - function _mintFee(uint112 _reserve0, uint112 _reserve1) private returns (bool feeOn) { - address feeTo = IUniswapV2Factory(factory).feeTo(); - feeOn = feeTo != address(0); - uint _kLast = kLast; // gas savings - if (feeOn) { - if (_kLast != 0) { - uint rootK = sqrt(uint(_reserve0).mul(_reserve1)); - uint rootKLast = sqrt(_kLast); - if (rootK > rootKLast) { - uint numerator = totalSupply.mul(rootK.sub(rootKLast)); - uint denominator = rootK.mul(5).add(rootKLast); - uint liquidity = numerator / denominator; - if (liquidity > 0) _mint(feeTo, liquidity); - } - } - } else if (_kLast != 0) { - kLast = 0; - } - } - - // this low-level function should be called from a contract which performs important safety checks - function mint(address to) external lock returns (uint liquidity) { - (uint112 _reserve0, uint112 _reserve1,) = getReserves(); // gas savings - uint balance0 = IToken(token0).balanceOf(address(this)); - uint balance1 = IToken(token1).balanceOf(address(this)); - uint amount0 = balance0.sub(_reserve0); - uint amount1 = balance1.sub(_reserve1); - - bool feeOn = _mintFee(_reserve0, _reserve1); - uint _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee - if (_totalSupply == 0) { - liquidity = sqrt(amount0.mul(amount1)).sub(MINIMUM_LIQUIDITY); - _mint(address(0), MINIMUM_LIQUIDITY); // permanently lock the first MINIMUM_LIQUIDITY tokens - } else { - liquidity = Math.min(amount0.mul(_totalSupply) / _reserve0, amount1.mul(_totalSupply) / _reserve1); - } - require(liquidity > 0, 'UniswapV2: INSUFFICIENT_LIQUIDITY_MINTED'); - _mint(to, liquidity); - - _update(balance0, balance1, _reserve0, _reserve1); - if (feeOn) kLast = uint(reserve0).mul(reserve1); // reserve0 and reserve1 are up-to-date - emit Mint(msg.sender, amount0, amount1); - } - - // this low-level function should be called from a contract which performs important safety checks - function burn(address to) external lock returns (uint amount0, uint amount1) { - (uint112 _reserve0, uint112 _reserve1,) = getReserves(); // gas savings - address _token0 = token0; // gas savings - address _token1 = token1; // gas savings - uint balance0 = IToken(_token0).balanceOf(address(this)); - uint balance1 = IToken(_token1).balanceOf(address(this)); - uint liquidity = balanceOf[address(this)]; - - bool feeOn = _mintFee(_reserve0, _reserve1); - uint _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee - amount0 = liquidity.mul(balance0) / _totalSupply; // using balances ensures pro-rata distribution - amount1 = liquidity.mul(balance1) / _totalSupply; // using balances ensures pro-rata distribution - require(amount0 > 0 && amount1 > 0, 'UniswapV2: INSUFFICIENT_LIQUIDITY_BURNED'); - _burn(address(this), liquidity); - _safeTransfer(_token0, to, amount0); - _safeTransfer(_token1, to, amount1); - balance0 = IToken(_token0).balanceOf(address(this)); - balance1 = IToken(_token1).balanceOf(address(this)); - - _update(balance0, balance1, _reserve0, _reserve1); - if (feeOn) kLast = uint(reserve0).mul(reserve1); // reserve0 and reserve1 are up-to-date - emit Burn(msg.sender, amount0, amount1, to); - } - - // this low-level function should be called from a contract which performs important safety checks - function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external lock { - require(amount0Out > 0 || amount1Out > 0, 'UniswapV2: INSUFFICIENT_OUTPUT_AMOUNT'); - (uint112 _reserve0, uint112 _reserve1,) = getReserves(); // gas savings - require(amount0Out < _reserve0 && amount1Out < _reserve1, 'UniswapV2: INSUFFICIENT_LIQUIDITY'); - - uint balance0; - uint balance1; - { // scope for _token{0,1}, avoids stack too deep errors - address _token0 = token0; - address _token1 = token1; - require(to != _token0 && to != _token1, 'UniswapV2: INVALID_TO'); - if (amount0Out > 0) _safeTransfer(_token0, to, amount0Out); // optimistically transfer tokens - if (amount1Out > 0) _safeTransfer(_token1, to, amount1Out); // optimistically transfer tokens - if (data.length > 0) IUniswapV2Callee(to).uniswapV2Call(msg.sender, amount0Out, amount1Out, data); - balance0 = IToken(_token0).balanceOf(address(this)); - balance1 = IToken(_token1).balanceOf(address(this)); - } - uint amount0In = balance0 > _reserve0 - amount0Out ? balance0 - (_reserve0 - amount0Out) : 0; - uint amount1In = balance1 > _reserve1 - amount1Out ? balance1 - (_reserve1 - amount1Out) : 0; - require(amount0In > 0 || amount1In > 0, 'UniswapV2: INSUFFICIENT_INPUT_AMOUNT'); - { // scope for reserve{0,1}Adjusted, avoids stack too deep errors - uint balance0Adjusted = balance0.mul(1000).sub(amount0In.mul(3)); - uint balance1Adjusted = balance1.mul(1000).sub(amount1In.mul(3)); - require(balance0Adjusted.mul(balance1Adjusted) >= uint(_reserve0).mul(_reserve1).mul(1000**2), 'UniswapV2: K'); - } - - _update(balance0, balance1, _reserve0, _reserve1); - emit Swap(msg.sender, amount0In, amount1In, amount0Out, amount1Out, to); - } - - // force balances to match reserves - function skim(address to) external lock { - address _token0 = token0; // gas savings - address _token1 = token1; // gas savings - _safeTransfer(_token0, to, IToken(_token0).balanceOf(address(this)).sub(reserve0)); - _safeTransfer(_token1, to, IToken(_token1).balanceOf(address(this)).sub(reserve1)); - } - - // force reserves to match balances - function sync() external lock { - _update(IToken(token0).balanceOf(address(this)), IToken(token1).balanceOf(address(this)), reserve0, reserve1); - } -} diff --git a/contracts/mock/MockWeth.sol b/contracts/mock/MockWeth.sol deleted file mode 100644 index 15a99972b..000000000 --- a/contracts/mock/MockWeth.sol +++ /dev/null @@ -1,53 +0,0 @@ -pragma solidity 0.5.7; - - -contract MockWeth { - string public name = "Wrapped Ether"; - string public symbol = "WETH"; - uint8 public decimals = 18; - - mapping (address => uint) public balanceOf; - mapping (address => mapping (address => uint)) public allowance; - - function() external payable { - deposit(); - } - function deposit() public payable { - balanceOf[msg.sender] += msg.value; - } - function withdraw(uint wad) public { - require(balanceOf[msg.sender] >= wad); - balanceOf[msg.sender] -= wad; - msg.sender.transfer(wad); - } - - function totalSupply() public view returns (uint) { - return address(this).balance; - } - - function approve(address guy, uint wad) public returns (bool) { - allowance[msg.sender][guy] = wad; - return true; - } - - function transfer(address dst, uint wad) public returns (bool) { - return transferFrom(msg.sender, dst, wad); - } - - function transferFrom(address src, address dst, uint wad) - public - returns (bool) - { - require(balanceOf[src] >= wad); - - if (src != msg.sender && allowance[src][msg.sender] != uint(-1)) { - require(allowance[src][msg.sender] >= wad); - allowance[src][msg.sender] -= wad; - } - - balanceOf[src] -= wad; - balanceOf[dst] += wad; - - return true; - } -} diff --git a/contracts/mock/TokenMock.sol b/contracts/mock/TokenMock.sol index eb787924e..73a1368ab 100644 --- a/contracts/mock/TokenMock.sol +++ b/contracts/mock/TokenMock.sol @@ -5,13 +5,12 @@ import "../external/openzeppelin-solidity/token/ERC20/ERC20.sol"; contract TokenMock is ERC20 { - string public name; - string public symbol; - uint8 public decimals = 18; + // string public name; + // string public symbol; + // uint8 public decimals = 18; - constructor(string memory tokenName, string memory tokenSymbol) public { - name = tokenName; - symbol = tokenSymbol; + constructor(string memory tokenName, string memory tokenSymbol) public ERC20(tokenName,tokenSymbol) { + } function mint(uint256 amount) public returns (uint256) { @@ -29,15 +28,15 @@ contract TokenMock is ERC20 { return true; } - /** - * @dev Burns a specific amount of tokens from the target address and decrements allowance - * @param from address The address which you want to send tokens from - * @param value uint256 The amount of token to be burned - */ - function burnFrom(address from, uint256 value) public returns (bool) { - _burnFrom(from, value); - return true; - } + // * + // * @dev Burns a specific amount of tokens from the target address and decrements allowance + // * @param from address The address which you want to send tokens from + // * @param value uint256 The amount of token to be burned + + // function burnFrom(address from, uint256 value) public returns (bool) { + // _burnFrom(from, value); + // return true; + // } /** * @dev Transfer token for a specified address @@ -46,7 +45,8 @@ contract TokenMock is ERC20 { */ function transfer(address to, uint256 value) public returns (bool) { - require(value <= _balances[msg.sender]); + // require(value <= _balances[msg.sender]); + require(value <= balanceOf(msg.sender)); _transfer(msg.sender, to, value); return true; } @@ -65,7 +65,7 @@ contract TokenMock is ERC20 { public returns (bool) { - _transferFrom(from, to, value); + super.transferFrom(from, to, value); return true; } @@ -75,7 +75,7 @@ contract TokenMock is ERC20 { * @return An uint256 representing the amount owned by the passed address. */ function balanceOf(address owner) public view returns (uint256) { - return _balances[owner]; + return super.balanceOf(owner);//_balances[owner]; } /** diff --git a/migrations/2_deploy.js b/migrations/2_deploy.js index e2bd7c416..b8c310a9b 100644 --- a/migrations/2_deploy.js +++ b/migrations/2_deploy.js @@ -1,71 +1,75 @@ const Master = artifacts.require('Master'); -const Plotus = artifacts.require('MockMarketRegistry'); const Governance = artifacts.require('MockGovernance'); const ProposalCategory = artifacts.require('ProposalCategory'); +const AllMarkets = artifacts.require('MockAllMarkets'); +const MarketCreationRewards = artifacts.require('MarketCreationRewards'); const MemberRoles = artifacts.require('MockMemberRoles'); const PlotusToken = artifacts.require('MockPLOT'); -const MockWeth = artifacts.require('MockWeth'); const TokenController = artifacts.require('MockTokenController'); const BLOT = artifacts.require('BLOT'); const MarketConfig = artifacts.require('MockConfig'); -const Market = artifacts.require('MockMarket'); -const MarketBTC = artifacts.require('MockBTCMarket'); const MockchainLink = artifacts.require('MockChainLinkAggregator'); -const MockUniswapRouter = artifacts.require('MockUniswapRouter'); -const MockUniswapFactory = artifacts.require('MockUniswapFactory'); const OwnedUpgradeabilityProxy = artifacts.require('OwnedUpgradeabilityProxy'); const Vesting = artifacts.require('Vesting'); +const { assert } = require("chai"); +const encode1 = require('../test/utils/encoder.js').encode1; const BN = web3.utils.BN; module.exports = function(deployer, network, accounts){ deployer.then(async () => { - let deployPlotus = await deployer.deploy(Plotus); let deployGovernance = await deployer.deploy(Governance); let deployProposalCategory = await deployer.deploy(ProposalCategory); let deployMemberRoles = await deployer.deploy(MemberRoles); - let deployMarket = await deployer.deploy(Market); let deployTokenController = await deployer.deploy(TokenController); - let deployPlotusToken = await deployer.deploy(PlotusToken, "30000000000000000000000000", accounts[0]); + let deployPlotusToken = await deployer.deploy(PlotusToken, "PLOT", "PLOT", 18,accounts[0], accounts[0]); + deployPlotusToken.mint(accounts[0],"30000000000000000000000000"); let mockchainLinkAggregaror = await deployer.deploy(MockchainLink); - let uniswapRouter = await deployer.deploy(MockUniswapRouter, deployPlotusToken.address); - let uniswapFactory = await deployer.deploy(MockUniswapFactory); let marketConfig = await deployer.deploy(MarketConfig); let plotusToken = await PlotusToken.at(deployPlotusToken.address); + let blotToken = await deployer.deploy(BLOT); let vestingContract = await deployer.deploy(Vesting, plotusToken.address, accounts[0]); let masterProxy = await deployer.deploy(Master); let master = await deployer.deploy(OwnedUpgradeabilityProxy, masterProxy.address); + let allMarkets = await deployer.deploy(AllMarkets); + let mcr = await deployer.deploy(MarketCreationRewards); master = await Master.at(master.address); - let implementations = [deployMemberRoles.address, deployProposalCategory.address, deployGovernance.address, deployPlotus.address, deployTokenController.address, blotToken.address]; - await master.initiateMaster(implementations, deployPlotusToken.address, accounts[0], marketConfig.address, [uniswapRouter.address, deployPlotusToken.address, uniswapFactory.address], vestingContract.address); - let mockWeth = await deployer.deploy(MockWeth); - let deployMarketBTC = await deployer.deploy(MarketBTC); + let implementations = [deployMemberRoles.address, deployProposalCategory.address, deployGovernance.address, deployTokenController.address, allMarkets.address, mcr.address, marketConfig.address, blotToken.address]; + await master.initiateMaster(implementations, deployPlotusToken.address, accounts[0], vestingContract.address); let tc = await TokenController.at(await master.getLatestAddress("0x5443")); - console.log(`Config: ${marketConfig.address}`); - console.log(`Token: ${plotusToken.address}`); - console.log(`TC: ${tc.address}`); let gvAddress = await master.getLatestAddress(web3.utils.toHex("GV")); master = await OwnedUpgradeabilityProxy.at(master.address); await master.transferProxyOwnership(gvAddress); master = await Master.at(master.address); await plotusToken.changeOperator(await master.getLatestAddress("0x5443")); - // await blotToken.changeOperator(await master.getLatestAddress("0x5443")); - let plotusAddress = await master.getLatestAddress(web3.utils.toHex("PL")); - let plotus = await Plotus.at(plotusAddress); - // await mockchainLinkAggregaror.setLatestAnswer(934999802346); var date = Date.now(); - date = Math.round(date/1000) + 10000 - let hash = await plotus.addInitialMarketTypesAndStart(date, deployMarket.address, deployMarketBTC.address); - console.log(hash.receipt.gasUsed); + date = Math.round(date/1000); let pc = await ProposalCategory.at(await master.getLatestAddress(web3.utils.toHex("PC"))); let mr = await MemberRoles.at(await master.getLatestAddress(web3.utils.toHex("MR"))); await mr.memberRolesInitiate([accounts[0]]); - console.log(await mr.checkRole(accounts[0], 1)); await pc.proposalCategoryInitiate(); - // console.log(await plotus.getOpenMarkets()); - await plotusToken.transfer(uniswapRouter.address, "100000000000000000000"); - await plotusToken.transfer(plotus.address, "10000000000000000000000"); + + let _marketUtility = await master.getLatestAddress(web3.utils.toHex("MU")); + let marketutility = await MarketConfig.at(_marketUtility); + await marketutility.setAssetPlotConversionRate(plotusToken.address, 1); + + + let allMarketsProxy = await OwnedUpgradeabilityProxy.at( + await master.getLatestAddress(web3.utils.toHex('AM')) + ); + + let mcrProxy = await OwnedUpgradeabilityProxy.at( + await master.getLatestAddress(web3.utils.toHex('MC')) + ); + + allMarkets = await AllMarkets.at(allMarketsProxy.address); + mcr = await MarketCreationRewards.at(mcrProxy.address); + + assert.equal(await master.isInternal(allMarkets.address), true); + assert.equal(await master.isInternal(mcr.address), true); + // await mcr.initialise() + await plotusToken.approve(allMarkets.address, "1000000000000000000000000") + await allMarkets.addInitialMarketTypesAndStart(date, mockchainLinkAggregaror.address, mockchainLinkAggregaror.address, accounts[0]); }); }; - diff --git a/package.json b/package.json index c7c33a88b..3c19b30fd 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,9 @@ "@openzeppelin/test-helpers": "^0.5.6", "bignumber.js": "^9.0.0", "coveralls": "^3.0.2", + "eip-712": "^0.4.2", "ethereumjs-abi": "^0.6.8", + "ethereumjs-util": "^7.0.7", "ganache-cli": "^6.9.0", "pify": "^5.0.0", "solhint": "^3.2.0", diff --git a/scripts/startGanache.bat b/scripts/startGanache.bat index 8ee6e7d79..5596dd2e0 100644 --- a/scripts/startGanache.bat +++ b/scripts/startGanache.bat @@ -2,5 +2,5 @@ echo Loading Resources . . . cd ../node_modules/.bin/ echo starting ganche-cli . . . -start cmd.exe /k "ganache-cli --gasLimit 0xfffffffffff -i 5777 -k 'constantinople' -p 8545 -m 'grocery obvious wire insane limit weather parade parrot patrol stock blast ivory' -a 47 -e 110 --gasPrice 0" +start cmd.exe /k "ganache-cli --gasLimit 0xfffffffffff -i 5777 -k 'constantinople' -p 8545 -m 'grocery obvious wire insane limit weather parade parrot patrol stock blast ivory' -a 47 -e 250 --gasPrice 0" ping 127.0.0.1 -n 5 > nul diff --git a/scripts/startGanache.sh b/scripts/startGanache.sh index c8d4d3935..8ce836ff4 100755 --- a/scripts/startGanache.sh +++ b/scripts/startGanache.sh @@ -2,5 +2,5 @@ echo Loading Resources . . . cd ../node_modules/.bin/ echo starting ganache-cli . . . -./ganache-cli --gasLimit 0xfffffffffff -i 5777 -k "constantinople" -p 8545 -m 'grocery obvious wire insane limit weather parade parrot patrol stock blast ivory' -a 47 -e 110 --gasPrice 0 +./ganache-cli --gasLimit 0xfffffffffff -i 5777 -k "constantinople" -p 8545 -m 'grocery obvious wire insane limit weather parade parrot patrol stock blast ivory' -a 47 -e 250 --gasPrice 0 ping 127.0.0.1 -n 5 > nul diff --git a/scripts/test.sh b/scripts/test.sh index 49070a591..3bd36c716 100755 --- a/scripts/test.sh +++ b/scripts/test.sh @@ -20,7 +20,7 @@ ganache_running() { } start_ganache() { - node_modules/.bin/ganache-cli --gasLimit 85000000 -k "constantinople" -p "$ganache_port" -i 5777 -m "grocery obvious wire insane limit weather parade parrot patrol stock blast ivory" -a 47 -e 110 --gasPrice 0 > /dev/null & + node_modules/.bin/ganache-cli --gasLimit 85000000 -k "constantinople" -p "$ganache_port" -i 5777 -m "grocery obvious wire insane limit weather parade parrot patrol stock blast ivory" -a 47 -e 250 --gasPrice 0 > /dev/null & ganache_pid=$! } diff --git a/test/01_4hourlyMarketOptionPrice.js b/test/01_4hourlyMarketOptionPrice.js new file mode 100644 index 000000000..5debe392e --- /dev/null +++ b/test/01_4hourlyMarketOptionPrice.js @@ -0,0 +1,234 @@ +const { assert } = require("chai"); +const OwnedUpgradeabilityProxy = artifacts.require("OwnedUpgradeabilityProxy"); +const Master = artifacts.require("Master"); +const TokenController = artifacts.require("TokenController"); +const PlotusToken = artifacts.require("MockPLOT"); +const MockchainLinkBTC = artifacts.require("MockChainLinkAggregator"); +const MarketConfig = artifacts.require("MockConfig"); +const BLOT = artifacts.require("BLOT"); +const AllMarkets = artifacts.require("AllMarkets"); +const increaseTime = require("./utils/increaseTime.js").increaseTime; +const increaseTimeTo = require("./utils/increaseTime.js").increaseTimeTo; +const { encode, encode1,encode3 } = require("./utils/encoder.js"); +const signAndExecuteMetaTx = require("./utils/signAndExecuteMetaTx.js").signAndExecuteMetaTx; +const { toHex, toWei, toChecksumAddress } = require("./utils/ethTools"); +let privateKeyList = ["fb437e3e01939d9d4fef43138249f23dc1d0852e69b0b5d1647c087f869fabbd","7c85a1f1da3120c941b83d71a154199ee763307683f206b98ad92c3b4e0af13e","ecc9b35bf13bd5459350da564646d05c5664a7476fe5acdf1305440f88ed784c","f4470c3fca4dbef1b2488d016fae25978effc586a1f83cb29ac8cb6ab5bc2d50","141319b1a84827e1046e93741bf8a9a15a916d49684ab04925ac4ce4573eea23","d54b606094287758dcf19064a8d91c727346aadaa9388732e73c4315b7c606f9","49030e42ce4152e715a7ddaa10e592f8e61d00f70ef11f48546711f159d985df","b96761b1e7ebd1e8464a78a98fe52f53ce6035c32b4b2b12307a629a551ff7cf","d4786e2581571c863c7d12231c3afb6d4cef390c0ac9a24b243293721d28ea95","ed28e3d3530544f1cf2b43d1956b7bd13b63c612d963a8fb37387aa1a5e11460","05b127365cf115d4978a7997ee98f9b48f0ddc552b981c18aa2ee1b3e6df42c6","9d11dd6843f298b01b34bd7f7e4b1037489871531d14b58199b7cba1ac0841e6","f79e90fa4091de4fc2ec70f5bf67b24393285c112658e0d810e6bd711387fbb9","99f1fc0f09230ce745b6a256ba7082e6e51a2907abda3d9e735a5c8188bb4ba1","477f86cce983b9c91a36fdcd4a7ce21144a08dee9b1aafb91b9c70e57f717ce6","b03d2e6bb4a7d71c66a66ff9e9c93549cae4b593f634a4ea2a1f79f94200f5b4","9ddc0f53a81e631dcf39d5155f41ec12ed551b731efc3224f410667ba07b37dc","cf087ff9ae7c9954ad8612d071e5cdf34a6024ee1ae477217639e63a802a53dd","b64f62b94babb82cc78d3d1308631ae221552bb595202fc1d267e1c29ce7ba60","a91e24875f8a534497459e5ccb872c4438be3130d8d74b7e1104c5f94cdcf8c2","4f49f3d029eeeb3fed14d59625acd088b6b34f3b41c527afa09d29e4a7725c32","179795fd7ac7e7efcba3c36d539a1e8659fb40d77d0a3fab2c25562d99793086","4ba37d0b40b879eceaaca2802a1635f2e6d86d5c31e3ff2d2fd13e68dd2a6d3d","6b7f5dfba9cd3108f1410b56f6a84188eee23ab48a3621b209a67eea64293394","870c540da9fafde331a3316cee50c17ad76ddb9160b78b317bef2e6f6fc4bac0","470b4cccaea895d8a5820aed088357e380d66b8e7510f0a1ea9b575850160241","8a55f8942af0aec1e0df3ab328b974a7888ffd60ded48cc6862013da0f41afbc","2e51e8409f28baf93e665df2a9d646a1bf9ac8703cbf9a6766cfdefa249d5780","99ef1a23e95910287d39493d8d9d7d1f0b498286f2b1fdbc0b01495f10cf0958","6652200c53a4551efe2a7541072d817562812003f9d9ef0ec17995aa232378f8","39c6c01194df72dda97da2072335c38231ced9b39afa280452afcca901e73643","12097e411d948f77b7b6fa4656c6573481c1b4e2864c1fca9d5b296096707c45","cbe53bf1976aee6cec830a848c6ac132def1503cffde82ccfe5bd15e75cbaa72","eeab5dcfff92dbabb7e285445aba47bd5135a4a3502df59ac546847aeb5a964f","5ea8279a578027abefab9c17cef186cccf000306685e5f2ee78bdf62cae568dd","0607767d89ad9c7686dbb01b37248290b2fa7364b2bf37d86afd51b88756fe66","e4fd5f45c08b52dae40f4cdff45e8681e76b5af5761356c4caed4ca750dc65cd","145b1c82caa2a6d703108444a5cf03e9cb8c3cd3f19299582a564276dbbba734","736b22ec91ae9b4b2b15e8d8c220f6c152d4f2228f6d46c16e6a9b98b4733120","ac776cb8b40f92cdd307b16b83e18eeb1fbaa5b5d6bd992b3fda0b4d6de8524c","65ba30e2202fdf6f37da0f7cfe31dfb5308c9209885aaf4cef4d572fd14e2903","54e8389455ec2252de063e83d3ce72529d674e6d2dc2070661f01d4f76b63475","fbbbfb525dd0255ee332d51f59648265aaa20c2e9eff007765cf4d4a6940a849","8de5e418f34d04f6ea947ce31852092a24a705862e6b810ca9f83c2d5f9cda4d","ea6040989964f012fd3a92a3170891f5f155430b8bbfa4976cde8d11513b62d9","14d94547b5deca767137fbd14dae73e888f3516c742fad18b83be333b38f0b88","47f05203f6368d56158cda2e79167777fc9dcb0c671ef3aabc205a1636c26a29"]; + +truncNumber = (n) => Math.trunc(n * Math.pow(10, 2)) / Math.pow(10, 2); +let masterInstance,plotusToken,BLOTInstance,MockchainLinkInstance,allMarkets; + +contract("Market", async function([user1, user2, user3, user4]) { + + before(async function () { + masterInstance = await OwnedUpgradeabilityProxy.deployed(); + masterInstance = await Master.at(masterInstance.address); + plotusToken = await PlotusToken.deployed(); + BLOTInstance = await BLOT.deployed(); + MockchainLinkInstance = await MockchainLinkBTC.deployed(); + allMarkets = await AllMarkets.at(await masterInstance.getLatestAddress(web3.utils.toHex("AM"))); + marketConfig = await MarketConfig.at(await masterInstance.getLatestAddress(web3.utils.toHex("MU"))); + + await marketConfig.setMockPriceFlag(false); + + let expireT = await allMarkets.getMarketData(1); + + await increaseTimeTo(expireT[5]); + + await MockchainLinkInstance.setLatestAnswer(1195000000000); + let currentPriceAfter = await MockchainLinkInstance.latestAnswer(); + }); + + it("1.Scenario 1 - Stake < minstakes and time passed < min time passed", async () => { + + await allMarkets.createMarket(0, 0); + await increaseTime(360); + + + await plotusToken.transfer(user2, toWei(10000)); + await plotusToken.approve(allMarkets.address, toWei(100000), { from: user2 }); + let functionSignature = encode3("depositAndPlacePrediction(uint,uint,address,uint64,uint256)", toWei(10000), 7, plotusToken.address, 10000*1e8, 1); + await signAndExecuteMetaTx( + privateKeyList[1], + user2, + functionSignature, + allMarkets, + "AM" + ); + + await plotusToken.transfer(user3, toWei(2000)); + await plotusToken.approve(allMarkets.address, toWei(100000), { from: user3 }); + functionSignature = encode3("depositAndPlacePrediction(uint,uint,address,uint64,uint256)", toWei(2000), 7, plotusToken.address, 2000*1e8, 2); + await signAndExecuteMetaTx( + privateKeyList[2], + user3, + functionSignature, + allMarkets, + "AM" + ); + + await plotusToken.transfer(user4, toWei(5000)); + await plotusToken.approve(allMarkets.address, toWei(100000), { from: user4 }); + functionSignature = encode3("depositAndPlacePrediction(uint,uint,address,uint64,uint256)", toWei(5000), 7, plotusToken.address, 5000*1e8, 3); + await signAndExecuteMetaTx( + privateKeyList[3], + user4, + functionSignature, + allMarkets, + "AM" + ); + assert.equal(await marketConfig.getOptionPrice(7,1), 25000); + assert.equal(await marketConfig.getOptionPrice(7,2), 50000); + assert.equal(await marketConfig.getOptionPrice(7,3), 25000); + }); + + it("2.Scenario 2 - Stake > minstakes and time passed < min time passed", async () => { + + + let expireT = await allMarkets.getMarketData(7); + + await increaseTimeTo(expireT[5]); + + await allMarkets.createMarket(0, 0); + + + + await plotusToken.transfer(user2, toWei(10000)); + await plotusToken.approve(allMarkets.address, toWei(100000), { from: user2 }); + let functionSignature = encode3("depositAndPlacePrediction(uint,uint,address,uint64,uint256)", toWei(10000), 8, plotusToken.address, 10000*1e8, 1); + await signAndExecuteMetaTx( + privateKeyList[1], + user2, + functionSignature, + allMarkets, + "AM" + ); + + await plotusToken.transfer(user3, toWei(5000)); + await plotusToken.approve(allMarkets.address, toWei(100000), { from: user3 }); + functionSignature = encode3("depositAndPlacePrediction(uint,uint,address,uint64,uint256)", toWei(5000), 8, plotusToken.address, 5000*1e8, 2); + await signAndExecuteMetaTx( + privateKeyList[2], + user3, + functionSignature, + allMarkets, + "AM" + ); + + await plotusToken.transfer(user4, toWei(40000)); + await plotusToken.approve(allMarkets.address, toWei(100000), { from: user4 }); + functionSignature = encode3("depositAndPlacePrediction(uint,uint,address,uint64,uint256)", toWei(40000), 8, plotusToken.address, 40000*1e8, 3); + await signAndExecuteMetaTx( + privateKeyList[3], + user4, + functionSignature, + allMarkets, + "AM" + ); + + let optionPricePaams = await allMarkets.getMarketOptionPricingParams(8,1); + await increaseTimeTo(optionPricePaams[1]/1+360); + + assert.equal(truncNumber((await marketConfig.getOptionPrice(8,1))/1e5), 0.19); + assert.equal(truncNumber((await marketConfig.getOptionPrice(8,2))/1e5), 0.16); + assert.equal(truncNumber((await marketConfig.getOptionPrice(8,3))/1e5), 0.63); + }); + + it("3.Scenario 3 - Stake > minstakes and time passed > min time passed", async () => { + + let expireT = await allMarkets.getMarketData(8); + + await increaseTimeTo(expireT[5]); + + await allMarkets.createMarket(0, 0); + + + await plotusToken.transfer(user2, toWei(10000)); + await plotusToken.approve(allMarkets.address, toWei(100000), { from: user2 }); + let functionSignature = encode3("depositAndPlacePrediction(uint,uint,address,uint64,uint256)", toWei(10000), 9, plotusToken.address, 10000*1e8, 1); + await signAndExecuteMetaTx( + privateKeyList[1], + user2, + functionSignature, + allMarkets, + "AM" + ); + + await plotusToken.transfer(user3, toWei(5000)); + await plotusToken.approve(allMarkets.address, toWei(100000), { from: user3 }); + functionSignature = encode3("depositAndPlacePrediction(uint,uint,address,uint64,uint256)", toWei(5000), 9, plotusToken.address, 5000*1e8, 2); + await signAndExecuteMetaTx( + privateKeyList[2], + user3, + functionSignature, + allMarkets, + "AM" + ); + + await plotusToken.transfer(user4, toWei(40000)); + await plotusToken.approve(allMarkets.address, toWei(100000), { from: user4 }); + functionSignature = encode3("depositAndPlacePrediction(uint,uint,address,uint64,uint256)", toWei(40000), 9, plotusToken.address, 40000*1e8, 3); + await signAndExecuteMetaTx( + privateKeyList[3], + user4, + functionSignature, + allMarkets, + "AM" + ); + + let optionPricePaams = await allMarkets.getMarketOptionPricingParams(9,1); + await increaseTimeTo(optionPricePaams[1]/1+41*60); + + assert.equal(truncNumber((await marketConfig.getOptionPrice(9,1))/1e5), 0.19); + assert.equal(truncNumber((await marketConfig.getOptionPrice(9,2))/1e5), 0.16); + assert.equal(truncNumber((await marketConfig.getOptionPrice(9,3))/1e5), 0.63); + }); + + it("4.Scenario 4 - Stake > minstakes and time passed > min time passed max distance = 2", async () => { + let expireT = await allMarkets.getMarketData(9); + + await increaseTimeTo(expireT[5]); + + await allMarkets.createMarket(0, 0); + + await plotusToken.transfer(user2, toWei(10000)); + await plotusToken.approve(allMarkets.address, toWei(100000), { from: user2 }); + let functionSignature = encode3("depositAndPlacePrediction(uint,uint,address,uint64,uint256)", toWei(10000), 10, plotusToken.address, 10000*1e8, 1); + await signAndExecuteMetaTx( + privateKeyList[1], + user2, + functionSignature, + allMarkets, + "AM" + ); + + await plotusToken.transfer(user3, toWei(5000)); + await plotusToken.approve(allMarkets.address, toWei(100000), { from: user3 }); + functionSignature = encode3("depositAndPlacePrediction(uint,uint,address,uint64,uint256)", toWei(5000), 10, plotusToken.address, 5000*1e8, 2); + await signAndExecuteMetaTx( + privateKeyList[2], + user3, + functionSignature, + allMarkets, + "AM" + ); + + await plotusToken.transfer(user4, toWei(40000)); + await plotusToken.approve(allMarkets.address, toWei(100000), { from: user4 }); + functionSignature = encode3("depositAndPlacePrediction(uint,uint,address,uint64,uint256)", toWei(40000), 10, plotusToken.address, 40000*1e8, 3); + await signAndExecuteMetaTx( + privateKeyList[3], + user4, + functionSignature, + allMarkets, + "AM" + ); + await MockchainLinkInstance.setLatestAnswer(1222000000000); + let optionPricePaams = await allMarkets.getMarketOptionPricingParams(10,1); + await increaseTimeTo(optionPricePaams[1]/1+41*60); + + assert.equal(truncNumber((await marketConfig.getOptionPrice(10,1))/1e5), 0.17); + assert.equal(truncNumber((await marketConfig.getOptionPrice(10,2))/1e5), 0.13); + assert.equal(truncNumber((await marketConfig.getOptionPrice(10,3))/1e5), 0.68); + }); + +}); diff --git a/test/01_4hourlyMarketOptionPriceManualFeed.js b/test/01_4hourlyMarketOptionPriceManualFeed.js new file mode 100644 index 000000000..2a2185807 --- /dev/null +++ b/test/01_4hourlyMarketOptionPriceManualFeed.js @@ -0,0 +1,254 @@ +const { assert } = require("chai"); +const OwnedUpgradeabilityProxy = artifacts.require("OwnedUpgradeabilityProxy"); +const Master = artifacts.require("Master"); +const TokenController = artifacts.require("TokenController"); +const PlotusToken = artifacts.require("MockPLOT"); +const MarketConfig = artifacts.require("MockConfig"); +const BLOT = artifacts.require("BLOT"); +const Governance = artifacts.require("Governance"); +const MemberRoles = artifacts.require("MemberRoles"); +const ProposalCategory = artifacts.require("ProposalCategory"); +const AllMarkets = artifacts.require("AllMarkets"); +const increaseTime = require("./utils/increaseTime.js").increaseTime; +const increaseTimeTo = require("./utils/increaseTime.js").increaseTimeTo; +const { encode, encode1,encode3 } = require("./utils/encoder.js"); +const signAndExecuteMetaTx = require("./utils/signAndExecuteMetaTx.js").signAndExecuteMetaTx; +const { toHex, toWei, toChecksumAddress } = require("./utils/ethTools"); +const latestTime = require("./utils/latestTime.js").latestTime; + +let privateKeyList = ["fb437e3e01939d9d4fef43138249f23dc1d0852e69b0b5d1647c087f869fabbd","7c85a1f1da3120c941b83d71a154199ee763307683f206b98ad92c3b4e0af13e","ecc9b35bf13bd5459350da564646d05c5664a7476fe5acdf1305440f88ed784c","f4470c3fca4dbef1b2488d016fae25978effc586a1f83cb29ac8cb6ab5bc2d50","141319b1a84827e1046e93741bf8a9a15a916d49684ab04925ac4ce4573eea23","d54b606094287758dcf19064a8d91c727346aadaa9388732e73c4315b7c606f9","49030e42ce4152e715a7ddaa10e592f8e61d00f70ef11f48546711f159d985df","b96761b1e7ebd1e8464a78a98fe52f53ce6035c32b4b2b12307a629a551ff7cf","d4786e2581571c863c7d12231c3afb6d4cef390c0ac9a24b243293721d28ea95","ed28e3d3530544f1cf2b43d1956b7bd13b63c612d963a8fb37387aa1a5e11460","05b127365cf115d4978a7997ee98f9b48f0ddc552b981c18aa2ee1b3e6df42c6","9d11dd6843f298b01b34bd7f7e4b1037489871531d14b58199b7cba1ac0841e6","f79e90fa4091de4fc2ec70f5bf67b24393285c112658e0d810e6bd711387fbb9","99f1fc0f09230ce745b6a256ba7082e6e51a2907abda3d9e735a5c8188bb4ba1","477f86cce983b9c91a36fdcd4a7ce21144a08dee9b1aafb91b9c70e57f717ce6","b03d2e6bb4a7d71c66a66ff9e9c93549cae4b593f634a4ea2a1f79f94200f5b4","9ddc0f53a81e631dcf39d5155f41ec12ed551b731efc3224f410667ba07b37dc","cf087ff9ae7c9954ad8612d071e5cdf34a6024ee1ae477217639e63a802a53dd","b64f62b94babb82cc78d3d1308631ae221552bb595202fc1d267e1c29ce7ba60","a91e24875f8a534497459e5ccb872c4438be3130d8d74b7e1104c5f94cdcf8c2","4f49f3d029eeeb3fed14d59625acd088b6b34f3b41c527afa09d29e4a7725c32","179795fd7ac7e7efcba3c36d539a1e8659fb40d77d0a3fab2c25562d99793086","4ba37d0b40b879eceaaca2802a1635f2e6d86d5c31e3ff2d2fd13e68dd2a6d3d","6b7f5dfba9cd3108f1410b56f6a84188eee23ab48a3621b209a67eea64293394","870c540da9fafde331a3316cee50c17ad76ddb9160b78b317bef2e6f6fc4bac0","470b4cccaea895d8a5820aed088357e380d66b8e7510f0a1ea9b575850160241","8a55f8942af0aec1e0df3ab328b974a7888ffd60ded48cc6862013da0f41afbc","2e51e8409f28baf93e665df2a9d646a1bf9ac8703cbf9a6766cfdefa249d5780","99ef1a23e95910287d39493d8d9d7d1f0b498286f2b1fdbc0b01495f10cf0958","6652200c53a4551efe2a7541072d817562812003f9d9ef0ec17995aa232378f8","39c6c01194df72dda97da2072335c38231ced9b39afa280452afcca901e73643","12097e411d948f77b7b6fa4656c6573481c1b4e2864c1fca9d5b296096707c45","cbe53bf1976aee6cec830a848c6ac132def1503cffde82ccfe5bd15e75cbaa72","eeab5dcfff92dbabb7e285445aba47bd5135a4a3502df59ac546847aeb5a964f","5ea8279a578027abefab9c17cef186cccf000306685e5f2ee78bdf62cae568dd","0607767d89ad9c7686dbb01b37248290b2fa7364b2bf37d86afd51b88756fe66","e4fd5f45c08b52dae40f4cdff45e8681e76b5af5761356c4caed4ca750dc65cd","145b1c82caa2a6d703108444a5cf03e9cb8c3cd3f19299582a564276dbbba734","736b22ec91ae9b4b2b15e8d8c220f6c152d4f2228f6d46c16e6a9b98b4733120","ac776cb8b40f92cdd307b16b83e18eeb1fbaa5b5d6bd992b3fda0b4d6de8524c","65ba30e2202fdf6f37da0f7cfe31dfb5308c9209885aaf4cef4d572fd14e2903","54e8389455ec2252de063e83d3ce72529d674e6d2dc2070661f01d4f76b63475","fbbbfb525dd0255ee332d51f59648265aaa20c2e9eff007765cf4d4a6940a849","8de5e418f34d04f6ea947ce31852092a24a705862e6b810ca9f83c2d5f9cda4d","ea6040989964f012fd3a92a3170891f5f155430b8bbfa4976cde8d11513b62d9","14d94547b5deca767137fbd14dae73e888f3516c742fad18b83be333b38f0b88","47f05203f6368d56158cda2e79167777fc9dcb0c671ef3aabc205a1636c26a29"]; +let nullAddress = "0x0000000000000000000000000000000000000000"; +truncNumber = (n) => Math.trunc(n * Math.pow(10, 2)) / Math.pow(10, 2); +let masterInstance,plotusToken,BLOTInstance,allMarkets,gv,mr,pc; + +contract("Market", async function([user1, user2, user3, user4]) { + + before(async function () { + masterInstance = await OwnedUpgradeabilityProxy.deployed(); + masterInstance = await Master.at(masterInstance.address); + plotusToken = await PlotusToken.deployed(); + BLOTInstance = await BLOT.deployed(); + allMarkets = await AllMarkets.at(await masterInstance.getLatestAddress(web3.utils.toHex("AM"))); + marketConfig = await MarketConfig.at(await masterInstance.getLatestAddress(web3.utils.toHex("MU"))); + let address = await masterInstance.getLatestAddress(toHex("GV")); + gv = await Governance.at(address); + address = await masterInstance.getLatestAddress(toHex("PC")); + pc = await ProposalCategory.at(address); + address = await masterInstance.getLatestAddress(toHex("MR")); + mr = await MemberRoles.at(address); + + await marketConfig.setMockPriceFlag(false); + + let expireT = await allMarkets.getMarketData(1); + + let pId = (await gv.getProposalLength()).toNumber(); + await gv.createProposal("Proposal2", "Proposal2", "Proposal2", 0); //Pid 3 + await gv.categorizeProposal(pId, 15, 0); + let startTime = (await latestTime()) / 1 + 2 * 604800; + let actionHash = encode("addMarketCurrency(bytes32,address,uint8,uint8,uint32)", toHex("ETH/PLOT"), nullAddress, 8, 1, startTime); + await gv.submitProposalWithSolution(pId, "addNewMarketCurrency", actionHash); + await gv.submitVote(pId, 1, { from: user1 }); + await increaseTime(604810); + await gv.closeProposal(pId); + let actionStatus = await gv.proposalActionStatus(pId); + assert.equal(actionStatus / 1, 3); + await increaseTime(604810); + + await marketConfig.setFeedPriceForMarketType(toHex("ETH/PLOT"),1195000000000); + }); + + it("1.Scenario 1 - Stake < minstakes and time passed < min time passed", async () => { + + + + await allMarkets.createMarket(2, 0); + await increaseTime(360); + + await plotusToken.transfer(user2, toWei(10000)); + await plotusToken.approve(allMarkets.address, toWei(100000), { from: user2 }); + let functionSignature = encode3("depositAndPlacePrediction(uint,uint,address,uint64,uint256)", toWei(10000), 7, plotusToken.address, 10000*1e8, 1); + await signAndExecuteMetaTx( + privateKeyList[1], + user2, + functionSignature, + allMarkets, + "AM" + ); + + await plotusToken.transfer(user3, toWei(2000)); + await plotusToken.approve(allMarkets.address, toWei(100000), { from: user3 }); + functionSignature = encode3("depositAndPlacePrediction(uint,uint,address,uint64,uint256)", toWei(2000), 7, plotusToken.address, 2000*1e8, 2); + await signAndExecuteMetaTx( + privateKeyList[2], + user3, + functionSignature, + allMarkets, + "AM" + ); + + await plotusToken.transfer(user4, toWei(5000)); + await plotusToken.approve(allMarkets.address, toWei(100000), { from: user4 }); + functionSignature = encode3("depositAndPlacePrediction(uint,uint,address,uint64,uint256)", toWei(5000), 7, plotusToken.address, 5000*1e8, 3); + await signAndExecuteMetaTx( + privateKeyList[3], + user4, + functionSignature, + allMarkets, + "AM" + ); + assert.equal(await marketConfig.getOptionPrice(7,1), 25000); + assert.equal(await marketConfig.getOptionPrice(7,2), 50000); + assert.equal(await marketConfig.getOptionPrice(7,3), 25000); + }); + + it("2.Scenario 2 - Stake > minstakes and time passed < min time passed", async () => { + + + let expireT = await allMarkets.getMarketData(7); + + await increaseTimeTo(expireT[5]); + + await allMarkets.createMarket(2, 0); + + + + await plotusToken.transfer(user2, toWei(10000)); + await plotusToken.approve(allMarkets.address, toWei(100000), { from: user2 }); + let functionSignature = encode3("depositAndPlacePrediction(uint,uint,address,uint64,uint256)", toWei(10000), 8, plotusToken.address, 10000*1e8, 1); + await signAndExecuteMetaTx( + privateKeyList[1], + user2, + functionSignature, + allMarkets, + "AM" + ); + + await plotusToken.transfer(user3, toWei(5000)); + await plotusToken.approve(allMarkets.address, toWei(100000), { from: user3 }); + functionSignature = encode3("depositAndPlacePrediction(uint,uint,address,uint64,uint256)", toWei(5000), 8, plotusToken.address, 5000*1e8, 2); + await signAndExecuteMetaTx( + privateKeyList[2], + user3, + functionSignature, + allMarkets, + "AM" + ); + + await plotusToken.transfer(user4, toWei(40000)); + await plotusToken.approve(allMarkets.address, toWei(100000), { from: user4 }); + functionSignature = encode3("depositAndPlacePrediction(uint,uint,address,uint64,uint256)", toWei(40000), 8, plotusToken.address, 40000*1e8, 3); + await signAndExecuteMetaTx( + privateKeyList[3], + user4, + functionSignature, + allMarkets, + "AM" + ); + + let optionPricePaams = await allMarkets.getMarketOptionPricingParams(8,1); + await increaseTimeTo(optionPricePaams[1]/1+360); + + assert.equal(truncNumber((await marketConfig.getOptionPrice(8,1))/1e5), 0.19); + assert.equal(truncNumber((await marketConfig.getOptionPrice(8,2))/1e5), 0.16); + assert.equal(truncNumber((await marketConfig.getOptionPrice(8,3))/1e5), 0.63); + }); + + it("3.Scenario 3 - Stake > minstakes and time passed > min time passed", async () => { + + let expireT = await allMarkets.getMarketData(8); + + await increaseTimeTo(expireT[5]); + + await allMarkets.createMarket(2, 0); + + + await plotusToken.transfer(user2, toWei(10000)); + await plotusToken.approve(allMarkets.address, toWei(100000), { from: user2 }); + let functionSignature = encode3("depositAndPlacePrediction(uint,uint,address,uint64,uint256)", toWei(10000), 9, plotusToken.address, 10000*1e8, 1); + await signAndExecuteMetaTx( + privateKeyList[1], + user2, + functionSignature, + allMarkets, + "AM" + ); + + await plotusToken.transfer(user3, toWei(5000)); + await plotusToken.approve(allMarkets.address, toWei(100000), { from: user3 }); + functionSignature = encode3("depositAndPlacePrediction(uint,uint,address,uint64,uint256)", toWei(5000), 9, plotusToken.address, 5000*1e8, 2); + await signAndExecuteMetaTx( + privateKeyList[2], + user3, + functionSignature, + allMarkets, + "AM" + ); + + await plotusToken.transfer(user4, toWei(40000)); + await plotusToken.approve(allMarkets.address, toWei(100000), { from: user4 }); + functionSignature = encode3("depositAndPlacePrediction(uint,uint,address,uint64,uint256)", toWei(40000), 9, plotusToken.address, 40000*1e8, 3); + await signAndExecuteMetaTx( + privateKeyList[3], + user4, + functionSignature, + allMarkets, + "AM" + ); + + let optionPricePaams = await allMarkets.getMarketOptionPricingParams(9,1); + await increaseTimeTo(optionPricePaams[1]/1+41*60); + + assert.equal(truncNumber((await marketConfig.getOptionPrice(9,1))/1e5), 0.19); + assert.equal(truncNumber((await marketConfig.getOptionPrice(9,2))/1e5), 0.16); + assert.equal(truncNumber((await marketConfig.getOptionPrice(9,3))/1e5), 0.63); + }); + + it("4.Scenario 4 - Stake > minstakes and time passed > min time passed max distance = 2", async () => { + let expireT = await allMarkets.getMarketData(9); + + await increaseTimeTo(expireT[5]); + + await allMarkets.createMarket(2, 0); + + await plotusToken.transfer(user2, toWei(10000)); + await plotusToken.approve(allMarkets.address, toWei(100000), { from: user2 }); + let functionSignature = encode3("depositAndPlacePrediction(uint,uint,address,uint64,uint256)", toWei(10000), 10, plotusToken.address, 10000*1e8, 1); + await signAndExecuteMetaTx( + privateKeyList[1], + user2, + functionSignature, + allMarkets, + "AM" + ); + + await plotusToken.transfer(user3, toWei(5000)); + await plotusToken.approve(allMarkets.address, toWei(100000), { from: user3 }); + functionSignature = encode3("depositAndPlacePrediction(uint,uint,address,uint64,uint256)", toWei(5000), 10, plotusToken.address, 5000*1e8, 2); + await signAndExecuteMetaTx( + privateKeyList[2], + user3, + functionSignature, + allMarkets, + "AM" + ); + + await plotusToken.transfer(user4, toWei(40000)); + await plotusToken.approve(allMarkets.address, toWei(100000), { from: user4 }); + functionSignature = encode3("depositAndPlacePrediction(uint,uint,address,uint64,uint256)", toWei(40000), 10, plotusToken.address, 40000*1e8, 3); + await signAndExecuteMetaTx( + privateKeyList[3], + user4, + functionSignature, + allMarkets, + "AM" + ); + await marketConfig.setFeedPriceForMarketType(toHex("ETH/PLOT"),1222000000000); + let optionPricePaams = await allMarkets.getMarketOptionPricingParams(10,1); + await increaseTimeTo(optionPricePaams[1]/1+41*60); + + assert.equal(truncNumber((await marketConfig.getOptionPrice(10,1))/1e5), 0.17); + assert.equal(truncNumber((await marketConfig.getOptionPrice(10,2))/1e5), 0.13); + assert.equal(truncNumber((await marketConfig.getOptionPrice(10,3))/1e5), 0.68); + }); + +}); diff --git a/test/01_hourlyMarketOptionPrice.js b/test/01_hourlyMarketOptionPrice.js deleted file mode 100644 index 92ad1b5f8..000000000 --- a/test/01_hourlyMarketOptionPrice.js +++ /dev/null @@ -1,711 +0,0 @@ -const { assert } = require("chai"); -const OwnedUpgradeabilityProxy = artifacts.require("OwnedUpgradeabilityProxy"); -const Market = artifacts.require("MockMarket"); -const Plotus = artifacts.require("MarketRegistry"); -const Master = artifacts.require("Master"); -const TokenController = artifacts.require("TokenController"); -const PlotusToken = artifacts.require("MockPLOT"); -const MockchainLinkBTC = artifacts.require("MockChainLinkAggregator"); -const MarketConfig = artifacts.require("MockConfig"); -const MockUniswapRouter = artifacts.require("MockUniswapRouter"); -const BLOT = artifacts.require("BLOT"); -const web3 = Market.web3; -const increaseTime = require("./utils/increaseTime.js").increaseTime; - -contract("Market", async function([user1, user2, user3, user4, user5, user6, user7, user8, user9, user10]) { - it("1.Scenario 1 - Stake in ETH < minstake (no stake in LOT) and time passed < min time passed", async () => { - let tokenPrice = 0.012; - let masterInstance = await OwnedUpgradeabilityProxy.deployed(); - masterInstance = await Master.at(masterInstance.address); - let plotusToken = await PlotusToken.deployed(); - let BLOTInstance = await BLOT.deployed(); - let MockchainLinkInstance = await MockchainLinkBTC.deployed(); - let plotusNewAddress = await masterInstance.getLatestAddress(web3.utils.toHex("PL")); - tokenController =await TokenController.at(await masterInstance.getLatestAddress(web3.utils.toHex("TC"))); - let MockUniswapRouterInstance = await MockUniswapRouter.deployed(); - let plotusNewInstance = await Plotus.at(plotusNewAddress); - let marketConfig = await plotusNewInstance.marketUtility(); - marketConfig = await MarketConfig.at(marketConfig); - const openMarkets = await plotusNewInstance.getOpenMarkets(); - - //console.log("marketType", openMarkets["_marketTypes"][0] / 1); - marketInstance = await Market.at(openMarkets["_openMarkets"][0]); - await marketConfig.setMockPriceFlag(false); - await increaseTime(10001); - assert.ok(marketInstance); - - await MockchainLinkInstance.setLatestAnswer(1195000000000); - let currentPriceAfter = await MockchainLinkInstance.latestAnswer(); - //console.log(currentPriceAfter / 1); - - await marketInstance.setOptionRangesPublic(11900, 12000); - let priceOption1 = await marketInstance.getOptionPrice(1); - let priceOption2 = await marketInstance.getOptionPrice(2); - let priceOption3 = await marketInstance.getOptionPrice(3); - //console.log(priceOption1 / 1, priceOption2 / 1, priceOption3 / 1); - - await MockUniswapRouterInstance.setPrice("12000000000000000"); - await marketConfig.setPrice("12000000000000000"); - - await marketInstance.placePrediction("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", "1000000000000000000", 1, 1, { - value: "1000000000000000000", - from: user1, - }); - - await marketInstance.placePrediction("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", "2000000000000000000", 2, 1, { - value: "2000000000000000000", - from: user2, - }); - - await marketInstance.placePrediction("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", "10000000000000000000", 3, 1, { - value: "10000000000000000000", - from: user3, - }); - - await increaseTime(360); - let currentPriceAfter_af = await MockchainLinkInstance.latestAnswer(); - //console.log(currentPriceAfter_af / 1); - let priceOption1_af = await marketInstance.getOptionPrice(1); - let priceOption2_af = await marketInstance.getOptionPrice(2); - let priceOption3_af = await marketInstance.getOptionPrice(3); - let optionPriceETH1 = priceOption1_af / 1; - let optionPriceLOT1 = priceOption1_af / tokenPrice; - //console.log("Round off ETH price of option1", optionPriceETH1 / 1000); - //console.log("Round off LOT price of option1", optionPriceLOT1 / 1000); - let optionPriceETH2 = priceOption2_af / 1; - let optionPriceLOT2 = priceOption2_af / 1 / tokenPrice; - //console.log("Round off ETH price of option2", optionPriceETH2 / 1000); - //console.log("Round off LOT price of option2", optionPriceLOT2 / 1000); - let optionPriceETH3 = priceOption3_af / 1; - let optionPriceLOT3 = priceOption3_af / 1 / tokenPrice; - //console.log("Round off ETH price of option3", optionPriceETH3 / 1000); - //console.log("Round off LOT price of option3", optionPriceLOT3 / 1000); - - assert.equal(parseFloat((optionPriceETH1 / 1000).toFixed(3)), 0.013); - assert.equal(parseFloat((optionPriceETH2 / 1000).toFixed(3)), 0.027); - assert.equal(parseFloat((optionPriceETH3 / 1000).toFixed(3)), 0.013); - assert.equal(parseFloat((optionPriceLOT1 / 1000).toFixed(3)), 1.083); - assert.equal(parseFloat((optionPriceLOT2 / 1000).toFixed(3)), 2.25); - assert.equal(parseFloat((optionPriceLOT3 / 1000).toFixed(3)), 1.083); - }); -}); - -contract("Market", async function([user1, user2, user3, user4, user5, user6, user7, user8, user9, user10]) { - it("2.Scenario 2 - Stake in LOT< minstake (no stake in ETH) and time passed < min time passed", async () => { - let tokenPrice = 0.012; - let masterInstance = await OwnedUpgradeabilityProxy.deployed(); - masterInstance = await Master.at(masterInstance.address); - let plotusToken = await PlotusToken.deployed(); - let BLOTInstance = await BLOT.deployed(); - let MockchainLinkInstance = await MockchainLinkBTC.deployed(); - let plotusNewAddress = await masterInstance.getLatestAddress(web3.utils.toHex("PL")); - tokenController =await TokenController.at(await masterInstance.getLatestAddress(web3.utils.toHex("TC"))); - let MockUniswapRouterInstance = await MockUniswapRouter.deployed(); - let plotusNewInstance = await Plotus.at(plotusNewAddress); - let marketConfig = await plotusNewInstance.marketUtility(); - marketConfig = await MarketConfig.at(marketConfig); - const openMarkets = await plotusNewInstance.getOpenMarkets(); - - //console.log("marketType", openMarkets["_marketTypes"][0] / 1); - marketInstance = await Market.at(openMarkets["_openMarkets"][0]); - await marketConfig.setMockPriceFlag(false); - await increaseTime(10001); - assert.ok(marketInstance); - - await MockchainLinkInstance.setLatestAnswer(1195000000000); - let currentPriceAfter = await MockchainLinkInstance.latestAnswer(); - //console.log(currentPriceAfter / 1); - - await marketInstance.setOptionRangesPublic(11900, 12000); - let priceOption1 = await marketInstance.getOptionPrice(1); - let priceOption2 = await marketInstance.getOptionPrice(2); - let priceOption3 = await marketInstance.getOptionPrice(3); - //console.log(priceOption1 / 1, priceOption2 / 1, priceOption3 / 1); - - await MockUniswapRouterInstance.setPrice("12000000000000000"); - await marketConfig.setPrice("12000000000000000"); - - await plotusToken.approve(tokenController.address, "10000000000000000000000"); - await marketInstance.placePrediction(plotusToken.address, "100000000000000000000", 1, 1, { - from: user1, - }); - - await marketInstance.placePrediction(plotusToken.address, "100000000000000000000", 2, 1, { - from: user1, - }); - - await marketInstance.placePrediction(plotusToken.address, "100000000000000000000", 3, 1, { - from: user1, - }); - - await increaseTime(360); - let currentPriceAfter_af = await MockchainLinkInstance.latestAnswer(); - //console.log(currentPriceAfter_af / 1); - let priceOption1_af = await marketInstance.getOptionPrice(1); - let priceOption2_af = await marketInstance.getOptionPrice(2); - let priceOption3_af = await marketInstance.getOptionPrice(3); - let optionPriceETH1 = priceOption1_af / 1; - let optionPriceLOT1 = priceOption1_af / tokenPrice; - //console.log("Round off ETH price of option1", optionPriceETH1 / 1000); - //console.log("Round off LOT price of option1", optionPriceLOT1 / 1000); - let optionPriceETH2 = priceOption2_af / 1; - let optionPriceLOT2 = priceOption2_af / 1 / tokenPrice; - //console.log("Round off ETH price of option2", optionPriceETH2 / 1000); - //console.log("Round off LOT price of option2", optionPriceLOT2 / 1000); - let optionPriceETH3 = priceOption3_af / 1; - let optionPriceLOT3 = priceOption3_af / 1 / tokenPrice; - //console.log("Round off ETH price of option3", optionPriceETH3 / 1000); - //console.log("Round off LOT price of option3", optionPriceLOT3 / 1000); - - assert.equal(parseFloat((optionPriceETH1 / 1000).toFixed(3)), 0.013); - assert.equal(parseFloat((optionPriceETH2 / 1000).toFixed(3)), 0.027); - assert.equal(parseFloat((optionPriceETH3 / 1000).toFixed(3)), 0.013); - assert.equal(parseFloat((optionPriceLOT1 / 1000).toFixed(3)), 1.083); - assert.equal(parseFloat((optionPriceLOT2 / 1000).toFixed(3)), 2.25); - assert.equal(parseFloat((optionPriceLOT3 / 1000).toFixed(3)), 1.083); - }); -}); - -contract("Market", async function([user1, user2, user3, user4, user5, user6, user7, user8, user9, user10]) { - it("3.Scenario 3 - Stake in LOT+ETH> minstake and time passed < min time passed", async () => { - let tokenPrice = 0.012; - let masterInstance = await OwnedUpgradeabilityProxy.deployed(); - masterInstance = await Master.at(masterInstance.address); - let plotusToken = await PlotusToken.deployed(); - let BLOTInstance = await BLOT.deployed(); - let MockchainLinkInstance = await MockchainLinkBTC.deployed(); - let plotusNewAddress = await masterInstance.getLatestAddress(web3.utils.toHex("PL")); - tokenController =await TokenController.at(await masterInstance.getLatestAddress(web3.utils.toHex("TC"))); - let MockUniswapRouterInstance = await MockUniswapRouter.deployed(); - let plotusNewInstance = await Plotus.at(plotusNewAddress); - let marketConfig = await plotusNewInstance.marketUtility(); - marketConfig = await MarketConfig.at(marketConfig); - const openMarkets = await plotusNewInstance.getOpenMarkets(); - - //console.log("marketType", openMarkets["_marketTypes"][0] / 1); - marketInstance = await Market.at(openMarkets["_openMarkets"][0]); - await marketConfig.setMockPriceFlag(false); - await increaseTime(10001); - assert.ok(marketInstance); - - await MockchainLinkInstance.setLatestAnswer(1195000000000); - let currentPriceAfter = await MockchainLinkInstance.latestAnswer(); - //console.log(currentPriceAfter / 1); - - await marketInstance.setOptionRangesPublic(11900, 12000); - let priceOption1 = await marketInstance.getOptionPrice(1); - let priceOption2 = await marketInstance.getOptionPrice(2); - let priceOption3 = await marketInstance.getOptionPrice(3); - //console.log(priceOption1 / 1, priceOption2 / 1, priceOption3 / 1); - - await MockUniswapRouterInstance.setPrice("12000000000000000"); - await marketConfig.setPrice("12000000000000000"); - - await plotusToken.approve(tokenController.address, "10000000000000000000000"); - await marketInstance.placePrediction(plotusToken.address, "1000000000000000000000", 1, 1, { - from: user1, - }); - - await marketInstance.placePrediction(plotusToken.address, "100000000000000000000", 2, 1, { - from: user1, - }); - - await marketInstance.placePrediction(plotusToken.address, "100000000000000000000", 3, 1, { - from: user1, - }); - - await marketInstance.placePrediction("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", "1000000000000000000", 1, 1, { - value: "1000000000000000000", - from: user1, - }); - - await marketInstance.placePrediction("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", "10000000000000000000", 2, 1, { - value: "10000000000000000000", - from: user2, - }); - - await marketInstance.placePrediction("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", "5000000000000000000", 3, 1, { - value: "5000000000000000000", - from: user2, - }); - - await increaseTime(360); - let currentPriceAfter_af = await MockchainLinkInstance.latestAnswer(); - //console.log(currentPriceAfter_af / 1); - let priceOption1_af = await marketInstance.getOptionPrice(1); - let priceOption2_af = await marketInstance.getOptionPrice(2); - let priceOption3_af = await marketInstance.getOptionPrice(3); - let optionPriceETH1 = priceOption1_af / 1; - let optionPriceLOT1 = priceOption1_af / tokenPrice; - //console.log("Round off ETH price of option1", optionPriceETH1 / 1000); - //console.log("Round off LOT price of option1", optionPriceLOT1 / 1000); - let optionPriceETH2 = priceOption2_af / 1; - let optionPriceLOT2 = priceOption2_af / 1 / tokenPrice; - //console.log("Round off ETH price of option2", optionPriceETH2 / 1000); - //console.log("Round off LOT price of option2", optionPriceLOT2 / 1000); - let optionPriceETH3 = priceOption3_af / 1; - let optionPriceLOT3 = priceOption3_af / 1 / tokenPrice; - //console.log("Round off ETH price of option3", optionPriceETH3 / 1000); - //console.log("Round off LOT price of option3", optionPriceLOT3 / 1000); - - assert.equal(parseFloat((optionPriceETH1 / 1000).toFixed(3)), 0.12); - assert.equal(parseFloat((optionPriceETH2 / 1000).toFixed(3)), 0.119); - assert.equal(parseFloat((optionPriceETH3 / 1000).toFixed(3)), 0.064); - assert.equal(parseFloat((optionPriceLOT1 / 1000).toFixed(3)), 10.0); - assert.equal(parseFloat((optionPriceLOT2 / 1000).toFixed(3)), 9.917); - assert.equal(parseFloat((optionPriceLOT3 / 1000).toFixed(3)), 5.333); - }); -}); - -contract("Market", async function([user1, user2, user3, user4, user5, user6, user7, user8, user9, user10]) { - it("4.Scenario 3 - Stake in LOT+ETH> minstake and time passed < min time passed", async () => { - let tokenPrice = 0.012; - let masterInstance = await OwnedUpgradeabilityProxy.deployed(); - masterInstance = await Master.at(masterInstance.address); - let plotusToken = await PlotusToken.deployed(); - let BLOTInstance = await BLOT.deployed(); - let MockchainLinkInstance = await MockchainLinkBTC.deployed(); - let plotusNewAddress = await masterInstance.getLatestAddress(web3.utils.toHex("PL")); - tokenController =await TokenController.at(await masterInstance.getLatestAddress(web3.utils.toHex("TC"))); - let MockUniswapRouterInstance = await MockUniswapRouter.deployed(); - let plotusNewInstance = await Plotus.at(plotusNewAddress); - let marketConfig = await plotusNewInstance.marketUtility(); - marketConfig = await MarketConfig.at(marketConfig); - const openMarkets = await plotusNewInstance.getOpenMarkets(); - - //console.log("marketType", openMarkets["_marketTypes"][0] / 1); - marketInstance = await Market.at(openMarkets["_openMarkets"][0]); - await marketConfig.setMockPriceFlag(false); - await increaseTime(10001); - assert.ok(marketInstance); - - await MockchainLinkInstance.setLatestAnswer(1195000000000); - let currentPriceAfter = await MockchainLinkInstance.latestAnswer(); - //console.log(currentPriceAfter / 1); - - await marketInstance.setOptionRangesPublic(11900, 12000); - let priceOption1 = await marketInstance.getOptionPrice(1); - let priceOption2 = await marketInstance.getOptionPrice(2); - let priceOption3 = await marketInstance.getOptionPrice(3); - //console.log(priceOption1 / 1, priceOption2 / 1, priceOption3 / 1); - - await MockUniswapRouterInstance.setPrice("12000000000000000"); - await marketConfig.setPrice("12000000000000000"); - - await plotusToken.approve(tokenController.address, "10000000000000000000000"); - await marketInstance.placePrediction(plotusToken.address, "1000000000000000000000", 1, 1, { - from: user1, - }); - - await marketInstance.placePrediction(plotusToken.address, "100000000000000000000", 2, 1, { - from: user1, - }); - - await marketInstance.placePrediction(plotusToken.address, "100000000000000000000", 3, 1, { - from: user1, - }); - - await marketInstance.placePrediction("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", "1000000000000000000", 1, 1, { - value: "1000000000000000000", - from: user1, - }); - - await marketInstance.placePrediction("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", "10000000000000000000", 2, 1, { - value: "10000000000000000000", - from: user2, - }); - - await marketInstance.placePrediction("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", "5000000000000000000", 3, 1, { - value: "5000000000000000000", - from: user2, - }); - - await increaseTime(360); - let currentPriceAfter_af = await MockchainLinkInstance.latestAnswer(); - //console.log(currentPriceAfter_af / 1); - let priceOption1_af = await marketInstance.getOptionPrice(1); - let priceOption2_af = await marketInstance.getOptionPrice(2); - let priceOption3_af = await marketInstance.getOptionPrice(3); - let optionPriceETH1 = priceOption1_af / 1; - let optionPriceLOT1 = priceOption1_af / tokenPrice; - //console.log("Round off ETH price of option1", optionPriceETH1 / 1000); - //console.log("Round off LOT price of option1", optionPriceLOT1 / 1000); - let optionPriceETH2 = priceOption2_af / 1; - let optionPriceLOT2 = priceOption2_af / 1 / tokenPrice; - //console.log("Round off ETH price of option2", optionPriceETH2 / 1000); - //console.log("Round off LOT price of option2", optionPriceLOT2 / 1000); - let optionPriceETH3 = priceOption3_af / 1; - let optionPriceLOT3 = priceOption3_af / 1 / tokenPrice; - //console.log("Round off ETH price of option3", optionPriceETH3 / 1000); - //console.log("Round off LOT price of option3", optionPriceLOT3 / 1000); - - assert.equal(parseFloat((optionPriceETH1 / 1000).toFixed(3)), 0.12); - assert.equal(parseFloat((optionPriceETH2 / 1000).toFixed(3)), 0.119); - assert.equal(parseFloat((optionPriceETH3 / 1000).toFixed(3)), 0.064); - assert.equal(parseFloat((optionPriceLOT1 / 1000).toFixed(3)), 10); - assert.equal(parseFloat((optionPriceLOT2 / 1000).toFixed(3)), 9.917); - assert.equal(parseFloat((optionPriceLOT3 / 1000).toFixed(3)), 5.333); - }); -}); - -contract("Market", async function([user1, user2, user3, user4, user5, user6, user7, user8, user9, user10]) { - it("5.Scenario 4 - Stake in LOT+ETH> minstake and time passed > min time passed", async () => { - let tokenPrice = 0.012; - let masterInstance = await OwnedUpgradeabilityProxy.deployed(); - masterInstance = await Master.at(masterInstance.address); - let plotusToken = await PlotusToken.deployed(); - let BLOTInstance = await BLOT.deployed(); - let MockchainLinkInstance = await MockchainLinkBTC.deployed(); - let plotusNewAddress = await masterInstance.getLatestAddress(web3.utils.toHex("PL")); - tokenController =await TokenController.at(await masterInstance.getLatestAddress(web3.utils.toHex("TC"))); - let MockUniswapRouterInstance = await MockUniswapRouter.deployed(); - let plotusNewInstance = await Plotus.at(plotusNewAddress); - let marketConfig = await plotusNewInstance.marketUtility(); - marketConfig = await MarketConfig.at(marketConfig); - const openMarkets = await plotusNewInstance.getOpenMarkets(); - - //console.log("marketType", openMarkets["_marketTypes"][0] / 1); - marketInstance = await Market.at(openMarkets["_openMarkets"][0]); - await marketConfig.setMockPriceFlag(false); - await increaseTime(10001); - assert.ok(marketInstance); - - await MockchainLinkInstance.setLatestAnswer(1195000000000); - let currentPriceAfter = await MockchainLinkInstance.latestAnswer(); - //console.log(currentPriceAfter / 1); - - await marketInstance.setOptionRangesPublic(11900, 12000); - let priceOption1 = await marketInstance.getOptionPrice(1); - let priceOption2 = await marketInstance.getOptionPrice(2); - let priceOption3 = await marketInstance.getOptionPrice(3); - //console.log(priceOption1 / 1, priceOption2 / 1, priceOption3 / 1); - - await MockUniswapRouterInstance.setPrice("12000000000000000"); - await marketConfig.setPrice("12000000000000000"); - - await plotusToken.approve(tokenController.address, "10000000000000000000000"); - await marketInstance.placePrediction(plotusToken.address, "1000000000000000000000", 1, 1, { - from: user1, - }); - - await marketInstance.placePrediction(plotusToken.address, "100000000000000000000", 2, 1, { - from: user1, - }); - - await marketInstance.placePrediction(plotusToken.address, "100000000000000000000", 3, 1, { - from: user1, - }); - - await marketInstance.placePrediction("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", "1000000000000000000", 1, 1, { - value: "1000000000000000000", - from: user1, - }); - - await marketInstance.placePrediction("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", "10000000000000000000", 2, 1, { - value: "10000000000000000000", - from: user2, - }); - - await marketInstance.placePrediction("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", "5000000000000000000", 3, 1, { - value: "5000000000000000000", - from: user2, - }); - - await increaseTime(1260); - let currentPriceAfter_af = await MockchainLinkInstance.latestAnswer(); - //console.log(currentPriceAfter_af / 1); - let priceOption1_af = await marketInstance.getOptionPrice(1); - let priceOption2_af = await marketInstance.getOptionPrice(2); - let priceOption3_af = await marketInstance.getOptionPrice(3); - let optionPriceETH1 = priceOption1_af / 1; - let optionPriceLOT1 = priceOption1_af / tokenPrice; - //console.log("Round off ETH price of option1", optionPriceETH1 / 1000); - //console.log("Round off LOT price of option1", optionPriceLOT1 / 1000); - let optionPriceETH2 = priceOption2_af / 1; - let optionPriceLOT2 = priceOption2_af / 1 / tokenPrice; - //console.log("Round off ETH price of option2", optionPriceETH2 / 1000); - //console.log("Round off LOT price of option2", optionPriceLOT2 / 1000); - let optionPriceETH3 = priceOption3_af / 1; - let optionPriceLOT3 = priceOption3_af / 1 / tokenPrice; - //console.log("Round off ETH price of option3", optionPriceETH3 / 1000); - //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(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)); - }); -}); - -contract("Market", async function([user1, user2, user3, user4, user5, user6, user7, user8, user9, user10]) { - it("6.Scenario 5 - Stake in LOT+ETH> minstake and time passed > min time passed, max distance = 2", async () => { - let tokenPrice = 0.012; - let masterInstance = await OwnedUpgradeabilityProxy.deployed(); - masterInstance = await Master.at(masterInstance.address); - let plotusToken = await PlotusToken.deployed(); - let BLOTInstance = await BLOT.deployed(); - let MockchainLinkInstance = await MockchainLinkBTC.deployed(); - let plotusNewAddress = await masterInstance.getLatestAddress(web3.utils.toHex("PL")); - tokenController =await TokenController.at(await masterInstance.getLatestAddress(web3.utils.toHex("TC"))); - let MockUniswapRouterInstance = await MockUniswapRouter.deployed(); - let plotusNewInstance = await Plotus.at(plotusNewAddress); - let marketConfig = await plotusNewInstance.marketUtility(); - marketConfig = await MarketConfig.at(marketConfig); - const openMarkets = await plotusNewInstance.getOpenMarkets(); - - //console.log("marketType", openMarkets["_marketTypes"][0] / 1); - marketInstance = await Market.at(openMarkets["_openMarkets"][0]); - await marketConfig.setMockPriceFlag(false); - await increaseTime(10001); - assert.ok(marketInstance); - - await MockchainLinkInstance.setLatestAnswer(1222000000000); - let currentPriceAfter = await MockchainLinkInstance.latestAnswer(); - //console.log(currentPriceAfter / 1); - - await marketInstance.setOptionRangesPublic(11900, 12000); - let priceOption1 = await marketInstance.getOptionPrice(1); - let priceOption2 = await marketInstance.getOptionPrice(2); - let priceOption3 = await marketInstance.getOptionPrice(3); - //console.log(priceOption1 / 1, priceOption2 / 1, priceOption3 / 1); - - await MockUniswapRouterInstance.setPrice("12000000000000000"); - await marketConfig.setPrice("12000000000000000"); - - await plotusToken.approve(tokenController.address, "10000000000000000000000"); - await marketInstance.placePrediction(plotusToken.address, "1000000000000000000000", 1, 1, { - from: user1, - }); - - await marketInstance.placePrediction(plotusToken.address, "100000000000000000000", 2, 1, { - from: user1, - }); - - await marketInstance.placePrediction(plotusToken.address, "100000000000000000000", 3, 1, { - from: user1, - }); - - await marketInstance.placePrediction("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", "1000000000000000000", 1, 1, { - value: "1000000000000000000", - from: user1, - }); - - await marketInstance.placePrediction("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", "10000000000000000000", 2, 1, { - value: "10000000000000000000", - from: user2, - }); - - await marketInstance.placePrediction("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", "5000000000000000000", 3, 1, { - value: "5000000000000000000", - from: user2, - }); - - await increaseTime(1211); - let currentPriceAfter_af = await MockchainLinkInstance.latestAnswer(); - //console.log(currentPriceAfter_af / 1); - let priceOption1_af = await marketInstance.getOptionPrice(1); - let priceOption2_af = await marketInstance.getOptionPrice(2); - let priceOption3_af = await marketInstance.getOptionPrice(3); - let optionPriceETH1 = priceOption1_af / 1; - let optionPriceLOT1 = priceOption1_af / tokenPrice; - //console.log("Round off ETH price of option1", optionPriceETH1 / 1000); - //console.log("Round off LOT price of option1", optionPriceLOT1 / 1000); - let optionPriceETH2 = priceOption2_af / 1; - let optionPriceLOT2 = priceOption2_af / 1 / tokenPrice; - //console.log("Round off ETH price of option2", optionPriceETH2 / 1000); - //console.log("Round off LOT price of option2", optionPriceLOT2 / 1000); - let optionPriceETH3 = priceOption3_af / 1; - let optionPriceLOT3 = priceOption3_af / 1 / tokenPrice; - //console.log("Round off ETH price of option3", optionPriceETH3 / 1000); - //console.log("Round off LOT price of option3", optionPriceLOT3 / 1000); - - assert.equal(parseFloat(Math.floor((optionPriceETH1 / 1000) * 100) / 100), 0.12); - assert.equal(parseFloat(Math.floor((optionPriceETH2 / 1000) * 100) / 100), 0.13); - assert.equal((optionPriceETH3 / 1000).toFixed(2), (0.109).toFixed(2)); - assert.equal(parseInt(optionPriceLOT1 / 1000) , parseInt(10.5)); - expect(optionPriceLOT2 / 1000).to.be.closeTo(10.8, 11.2);//10.83 - expect(optionPriceLOT3 / 1000).to.be.closeTo(9, 9.4);//9.08 - }); -}); -contract("Market", async function([user1, user2, user3, user4, user5, user6, user7, user8, user9, user10]) { - it("7.Scenario 7 - Stake in LOT+ETH> minstake and time passed > min time passed", async () => { - let tokenPrice = 0.012; - let masterInstance = await OwnedUpgradeabilityProxy.deployed(); - masterInstance = await Master.at(masterInstance.address); - let plotusToken = await PlotusToken.deployed(); - let BLOTInstance = await BLOT.deployed(); - let MockchainLinkInstance = await MockchainLinkBTC.deployed(); - let plotusNewAddress = await masterInstance.getLatestAddress(web3.utils.toHex("PL")); - tokenController =await TokenController.at(await masterInstance.getLatestAddress(web3.utils.toHex("TC"))); - let MockUniswapRouterInstance = await MockUniswapRouter.deployed(); - let plotusNewInstance = await Plotus.at(plotusNewAddress); - let marketConfig = await plotusNewInstance.marketUtility(); - marketConfig = await MarketConfig.at(marketConfig); - const openMarkets = await plotusNewInstance.getOpenMarkets(); - - //console.log("marketType", openMarkets["_marketTypes"][0] / 1); - marketInstance = await Market.at(openMarkets["_openMarkets"][0]); - await marketConfig.setMockPriceFlag(false); - await increaseTime(10001); - assert.ok(marketInstance); - - await MockchainLinkInstance.setLatestAnswer(1195000000000); - let currentPriceAfter = await MockchainLinkInstance.latestAnswer(); - //console.log(currentPriceAfter / 1); - - await marketInstance.setOptionRangesPublic(11900, 12000); - let priceOption1 = await marketInstance.getOptionPrice(1); - let priceOption2 = await marketInstance.getOptionPrice(2); - let priceOption3 = await marketInstance.getOptionPrice(3); - //console.log(priceOption1 / 1, priceOption2 / 1, priceOption3 / 1); - - await MockUniswapRouterInstance.setPrice("12000000000000000"); - await marketConfig.setPrice("12000000000000000"); - - await plotusToken.approve(tokenController.address, "10000000000000000000000"); - await marketInstance.placePrediction(plotusToken.address, "1000000000000000000000", 1, 1, { - from: user1, - }); - - await marketInstance.placePrediction(plotusToken.address, "100000000000000000000", 2, 1, { - from: user1, - }); - - await marketInstance.placePrediction(plotusToken.address, "100000000000000000000", 3, 1, { - from: user1, - }); - - await marketInstance.placePrediction("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", "1000000000000000000", 1, 1, { - value: "1000000000000000000", - from: user1, - }); - - await marketInstance.placePrediction("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", "11000000000000000000", 2, 1, { - value: "11000000000000000000", - from: user2, - }); - - await marketInstance.placePrediction("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", "5000000000000000000", 3, 1, { - value: "5000000000000000000", - from: user2, - }); - - await increaseTime(1211); - let currentPriceAfter_af = await MockchainLinkInstance.latestAnswer(); - //console.log(currentPriceAfter_af / 1); - let priceOption1_af = await marketInstance.getOptionPrice(1); - let priceOption2_af = await marketInstance.getOptionPrice(2); - let priceOption3_af = await marketInstance.getOptionPrice(3); - let optionPriceETH1 = priceOption1_af / 1; - let optionPriceLOT1 = priceOption1_af / tokenPrice; - //console.log("Round off ETH price of option1", optionPriceETH1 / 1000); - //console.log("Round off LOT price of option1", optionPriceLOT1 / 1000); - let optionPriceETH2 = priceOption2_af / 1; - let optionPriceLOT2 = priceOption2_af / 1 / tokenPrice; - //console.log("Round off ETH price of option2", optionPriceETH2 / 1000); - //console.log("Round off LOT price of option2", optionPriceLOT2 / 1000); - let optionPriceETH3 = priceOption3_af / 1; - let optionPriceLOT3 = priceOption3_af / 1 / tokenPrice; - //console.log("Round off ETH price of option3", optionPriceETH3 / 1000); - //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((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 - expect(optionPriceLOT3 / 1000).to.be.closeTo(6.5, 6.7);//6.5 - }); -}); -contract("Market", async function([user1, user2, user3, user4, user5, user6, user7, user8, user9, user10]) { - it("8.Scenario 8 - Stake in LOT+ETH> minstake and time passed > min time passed, max distance = 2 OPTION 1", async () => { - let tokenPrice = 0.012; - let masterInstance = await OwnedUpgradeabilityProxy.deployed(); - masterInstance = await Master.at(masterInstance.address); - let plotusToken = await PlotusToken.deployed(); - let BLOTInstance = await BLOT.deployed(); - let MockchainLinkInstance = await MockchainLinkBTC.deployed(); - let plotusNewAddress = await masterInstance.getLatestAddress(web3.utils.toHex("PL")); - tokenController =await TokenController.at(await masterInstance.getLatestAddress(web3.utils.toHex("TC"))); - let MockUniswapRouterInstance = await MockUniswapRouter.deployed(); - let plotusNewInstance = await Plotus.at(plotusNewAddress); - let marketConfig = await plotusNewInstance.marketUtility(); - marketConfig = await MarketConfig.at(marketConfig); - const openMarkets = await plotusNewInstance.getOpenMarkets(); - - //console.log("marketType", openMarkets["_marketTypes"][0] / 1); - marketInstance = await Market.at(openMarkets["_openMarkets"][0]); - await marketConfig.setMockPriceFlag(false); - await increaseTime(10001); - assert.ok(marketInstance); - - await MockchainLinkInstance.setLatestAnswer(1155000000000); - let currentPriceAfter = await MockchainLinkInstance.latestAnswer(); - //console.log(currentPriceAfter / 1); - - await marketInstance.setOptionRangesPublic(11900, 12000); - let priceOption1 = await marketInstance.getOptionPrice(1); - let priceOption2 = await marketInstance.getOptionPrice(2); - let priceOption3 = await marketInstance.getOptionPrice(3); - //console.log(priceOption1 / 1, priceOption2 / 1, priceOption3 / 1); - - await MockUniswapRouterInstance.setPrice("12000000000000000"); - await marketConfig.setPrice("12000000000000000"); - - await plotusToken.approve(tokenController.address, "10000000000000000000000"); - await marketInstance.placePrediction(plotusToken.address, "1000000000000000000000", 1, 1, { - from: user1, - }); - - await marketInstance.placePrediction(plotusToken.address, "100000000000000000000", 2, 1, { - from: user1, - }); - - await marketInstance.placePrediction(plotusToken.address, "100000000000000000000", 3, 1, { - from: user1, - }); - - await marketInstance.placePrediction("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", "1000000000000000000", 1, 1, { - value: "1000000000000000000", - from: user1, - }); - - await marketInstance.placePrediction("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", "11000000000000000000", 2, 1, { - value: "11000000000000000000", - from: user2, - }); - - await marketInstance.placePrediction("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", "5000000000000000000", 3, 1, { - value: "5000000000000000000", - from: user2, - }); - - await increaseTime(1211); - let currentPriceAfter_af = await MockchainLinkInstance.latestAnswer(); - ////console.log(currentPriceAfter_af / 1); - let priceOption1_af = await marketInstance.getOptionPrice(1); - let priceOption2_af = await marketInstance.getOptionPrice(2); - let priceOption3_af = await marketInstance.getOptionPrice(3); - let optionPriceETH1 = priceOption1_af / 1; - let optionPriceLOT1 = priceOption1_af / tokenPrice; - //console.log("Round off ETH price of option1", optionPriceETH1 / 1000); - //console.log("Round off LOT price of option1", optionPriceLOT1 / 1000); - let optionPriceETH2 = priceOption2_af / 1; - let optionPriceLOT2 = priceOption2_af / 1 / tokenPrice; - //console.log("Round off ETH price of option2", optionPriceETH2 / 1000); - //console.log("Round off LOT price of option2", optionPriceLOT2 / 1000); - let optionPriceETH3 = priceOption3_af / 1; - let optionPriceLOT3 = priceOption3_af / 1 / tokenPrice; - //console.log("Round off ETH price of option3", optionPriceETH3 / 1000); - //console.log("Round off LOT price of option3", optionPriceLOT3 / 1000); - - assert.equal(parseFloat(Math.floor((optionPriceETH1 / 1000) * 100) / 100), 0.16); - assert.equal(parseFloat(Math.floor((optionPriceETH2 / 1000) * 100) / 100), 0.13); - assert.equal((optionPriceETH3 / 1000).toFixed(2), (0.068).toFixed(2)); - assert.equal(parseInt(optionPriceLOT1 / 1000) , parseInt(13.41)); - assert.equal(parseInt(optionPriceLOT2 / 1000) , parseInt(11.33)); - assert.equal(parseInt(optionPriceLOT3 / 1000) , parseInt(5.66)); - }); -}); diff --git a/test/02_AirdropBlot.test.js b/test/02_AirdropBlot.test.js deleted file mode 100644 index 910b015b6..000000000 --- a/test/02_AirdropBlot.test.js +++ /dev/null @@ -1,442 +0,0 @@ -const { assert } = require("chai"); - -const OwnedUpgradeabilityProxy = artifacts.require("OwnedUpgradeabilityProxy"); -const Market = artifacts.require("MockMarket"); -const Plotus = artifacts.require("MarketRegistry"); -const Master = artifacts.require("Master"); -const Airdrop = artifacts.require("Airdrop"); -const MarketConfig = artifacts.require("MockConfig"); -const PlotusToken = artifacts.require("MockPLOT"); -const TokenController = artifacts.require("TokenController"); -const BLOT = artifacts.require("BLOT"); -const MockUniswapRouter = artifacts.require("MockUniswapRouter"); -const BigNumber = require("bignumber.js"); - -const web3 = Market.web3; -const increaseTime = require("./utils/increaseTime.js").increaseTime; -const assertRevert = require("./utils/assertRevert.js").assertRevert; -const latestTime = require("./utils/latestTime.js").latestTime; -const { toHex, toWei } = require("./utils/ethTools.js"); - -const nullAddress = "0x0000000000000000000000000000000000000000"; -// get etherum accounts -// swap ether with LOT -let airdrop; -contract("Airdrop", async function([user1, user2, user3, user4, user5, user6, user7, user8, user9, user10]) { - it("Place the prediction with ether", async () => { - masterInstance = await OwnedUpgradeabilityProxy.deployed(); - masterInstance = await Master.at(masterInstance.address); - plotusToken = await PlotusToken.deployed(); - BLOTInstance = await BLOT.at(await masterInstance.getLatestAddress(web3.utils.toHex("BL"))); - MockUniswapRouterInstance = await MockUniswapRouter.deployed(); - plotusNewAddress = await masterInstance.getLatestAddress(web3.utils.toHex("PL")); - tokenController =await TokenController.at(await masterInstance.getLatestAddress(web3.utils.toHex("TC"))); - plotusNewInstance = await Plotus.at(plotusNewAddress); - marketConfig = await plotusNewInstance.marketUtility(); - marketConfig = await MarketConfig.at(marketConfig); - // console.log(await plotusNewInstance.getOpenMarkets()); - openMarkets = await plotusNewInstance.getOpenMarkets(); - let endDate = (await latestTime())/1+(24*3600); - airdrop = await Airdrop.new(plotusToken.address, BLOTInstance.address, endDate, toWei("1000")); - - await BLOTInstance.addMinter(airdrop.address); - - await plotusToken.transfer(airdrop.address,toWei("1000")); - - await airdrop.airdropBLot([user2,user4],["400000000000000000000","124000000000000000000"]); - - - // console.log(`OpenMaket : ${openMarkets["_openMarkets"][0]}`); - - marketInstance = await Market.at(openMarkets["_openMarkets"][0]); - await increaseTime(10001); - assert.ok(marketInstance); - - // setting option price in eth - await marketConfig.setOptionPrice(1, 9); - await marketConfig.setOptionPrice(2, 18); - await marketConfig.setOptionPrice(3, 27); - - await assertRevert(marketInstance.calculatePredictionResult(1)); //should revert as market is in live status - - // set price - // user 1 - // set price lot - await MockUniswapRouterInstance.setPrice("1000000000000000"); - await marketConfig.setPrice("1000000000000000"); - await plotusToken.approve(tokenController.address, "100000000000000000000", { - from: user1, - }); - await marketInstance.placePrediction(plotusToken.address, "100000000000000000000", 2, 1, { from: user1 }); - - // user 2 - await MockUniswapRouterInstance.setPrice("2000000000000000"); - await marketConfig.setPrice("2000000000000000"); - // await plotusToken.transfer(user2, "500000000000000000000"); - - // await plotusToken.approve( - // openMarkets["_openMarkets"][0], - // "400000000000000000000", - // { - // from: user2, - // } - // ); - // await marketInstance.placePrediction( - // plotusToken.address, - // "400000000000000000000", - // 2, - // 2, - // { from: user2 } - // ); - await plotusToken.approve(BLOTInstance.address, "4000000000000000000000"); - // await BLOTInstance.mint(user2, "400000000000000000000"); - await airdrop.claim({from:user2}); - - // await BLOTInstance.transferFrom(user1, user2, "500000000000000000000", { - // from: user1, - // }); - - // await BLOTInstance.approve(openMarkets["_openMarkets"][0], "400000000000000000000", { - // from: user2, - // }); - // console.log(await BLOTInstance.balanceOf(user1)); - // await BLOTInstance.addMinter(marketInstance.address); - await marketInstance.placePrediction(BLOTInstance.address, "400000000000000000000", 2, 5, { from: user2 }); - let flags = await marketInstance.getUserFlags(user2); - assert.equal(flags[1], true); - // user 3 - await MockUniswapRouterInstance.setPrice("1000000000000000"); - await marketConfig.setPrice("1000000000000000"); - await plotusToken.transfer(user3, "500000000000000000000"); - await plotusToken.approve(tokenController.address, "210000000000000000000", { - from: user3, - }); - - await assertRevert(marketInstance.placePrediction(user10, "210000000000000000000", 2, 2, { from: user3 })); //should revert as assert not valid - await assertRevert(marketInstance.placePrediction(plotusToken.address, "210000000000000000000", 2, 2, { from: user3, value: "100" })); // should revert as passing value - await assertRevert(marketInstance.placePrediction(plotusToken.address, "1", 2, 2, { from: user3 })); // should revert as prediction amount is less than min required prediction - // try { - // await marketInstance.placePrediction(plotusToken.address, "600000000000000000000", 2, 2, { from: user3 }); // should revert as user do not have enough asset - // assert.fail(); - // } catch (e) { - // console.log(e); - // } - - await marketInstance.placePrediction(plotusToken.address, "210000000000000000000", 2, 2, { from: user3 }); - // user 4 - await MockUniswapRouterInstance.setPrice("15000000000000000"); - await marketConfig.setPrice("15000000000000000"); - - await plotusToken.approve(BLOTInstance.address, "124000000000000000000"); - // await BLOTInstance.mint(user4, "124000000000000000000"); - await airdrop.claim({from:user4}); - - // await BLOTInstance.approve(openMarkets["_openMarkets"][0], "124000000000000000000", { - // from: user4, - // }); - - await assertRevert(marketInstance.placePrediction(BLOTInstance.address, "123000000000000000000", 3, 4, { from: user4 })); //should revert as leverage is not 5 - await assertRevert( - marketInstance.placePrediction(BLOTInstance.address, "123000000000000000000", 3, 5, { from: user4, value: "1000000000000000000" }) - ); // should revert as passing value - - await marketInstance.placePrediction(BLOTInstance.address, "123000000000000000000", 3, 5, { from: user4 }); - - await assertRevert(marketInstance.placePrediction(BLOTInstance.address, "1000000000000000000", 3, 5, { from: user4 })); //should revert as once usr can only place prediction with BLOT once in a market - - // await plotusToken.transfer(user4, "200000000000000000000"); - - // await plotusToken.approve( - // openMarkets["_openMarkets"][0], - // "123000000000000000000", - // { - // from: user4, - // } - // ); - // await marketInstance.placePrediction( - // plotusToken.address, - // "123000000000000000000", - // 3, - // 3, - // { from: user4 } - // ); - - // user 5 - await MockUniswapRouterInstance.setPrice("12000000000000000"); - await marketConfig.setPrice("12000000000000000"); - await assertRevert( - marketInstance.placePrediction("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", "1000000000000000000", 1, 4, { - value: "100000000000000000", - from: user5, - }) - ); - await marketInstance.placePrediction("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", "1000000000000000000", 1, 4, { - value: "1000000000000000000", - from: user5, - }); - - // user 6 - await MockUniswapRouterInstance.setPrice("14000000000000000"); - await marketConfig.setPrice("14000000000000000"); - await marketInstance.placePrediction("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", "2000000000000000000", 1, 5, { - value: "2000000000000000000", - from: user6, - }); - // user 7 - await MockUniswapRouterInstance.setPrice("10000000000000000"); - await marketConfig.setPrice("10000000000000000"); - - await marketInstance.placePrediction("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", "1000000000000000000", 2, 2, { - value: "1000000000000000000", - from: user7, - }); - // user 8 - await MockUniswapRouterInstance.setPrice("45000000000000000"); - await marketConfig.setPrice("45000000000000000"); - await marketInstance.placePrediction("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", "3000000000000000000", 3, 3, { - value: "3000000000000000000", - from: user8, - }); - // user 9 - await MockUniswapRouterInstance.setPrice("51000000000000000"); - await marketConfig.setPrice("51000000000000000"); - await marketInstance.placePrediction("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", "1000000000000000000", 3, 1, { - value: "1000000000000000000", - from: user9, - }); - // user 10 - await MockUniswapRouterInstance.setPrice("12000000000000000"); - await marketConfig.setPrice("12000000000000000"); - await marketInstance.placePrediction("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", "2000000000000000000", 2, 4, { - value: "2000000000000000000", - from: user10, - }); - }); - - it("1.Prediction Points allocated properly in ether", async () => { - accounts = [user1, user2, user3, user4, user5, user6, user7, user8, user9, user10]; - options = [2, 2, 2, 3, 1, 1, 2, 3, 3, 2]; - getPredictionPoints = async (user, option, expected) => { - // return Prediction points of user - let PredictionPoins = await marketInstance.getUserPredictionPoints(user, option); - PredictionPoins = PredictionPoins / 1; - return PredictionPoins; - }; - PredictionPointsExpected = [1.755503471, 238.3350545, 11.21889102, 556.4885586, 510.3, 1882.8, 116.5, 634.1, 37.0, 721.7]; - - // console.log("Prediction points for user 1"); - // PredictionPointsUser1 = await getPredictionPoints(accounts[0], options[0]); - // PredictionPointsUser3 = await getPredictionPoints(accounts[2], options[2]); - - // console.log( - // `Prediction points : ${PredictionPointsUser1} expected : ${PredictionPointsExpected[0]} ` - // ); - // console.log("Prediction points for user 3"); - // console.log( - // `Prediction points : ${PredictionPointsUser3} expected : ${PredictionPointsExpected[2]} ` - // ); - for (let index = 0; index < 10; index++) { - let PredictionPoints = await getPredictionPoints(accounts[index], options[index]); - PredictionPoints = PredictionPoints / 1000; - PredictionPoints = PredictionPoints.toFixed(1); - assert.equal(PredictionPoints, PredictionPointsExpected[index].toFixed(1)); - // commented by parv (as already added assert above) - // console.log(`user${index + 1} : option : ${options[index]} `); - // console.log(`Prediction points : ${PredictionPoints} expected : ${PredictionPointsExpected[index].toFixed(1)} `); - } - // console.log(await plotusToken.balanceOf(user1)); - - // close market - await increaseTime(36001); - await marketInstance.calculatePredictionResult(1); - await increaseTime(36001); - // console.log((await web3.eth.getBalance(marketInstance.address))/1) - // plotus contract balance eth balance - plotusBalanceBefore = await web3.eth.getBalance(plotusNewAddress); - assert.equal(parseFloat(plotusBalanceBefore), "10000000000000000"); - lotBalanceBefore = await plotusToken.balanceOf(openMarkets["_openMarkets"][0]); - assert.equal(parseFloat(web3.utils.fromWei(lotBalanceBefore)).toFixed(2), (832.5835).toFixed(2)); - - // lot supply , lot balance of market - await MockUniswapRouterInstance.setPrice("1000000000000000"); - await marketConfig.setPrice("1000000000000000"); - - - plotusBalanceAfter = await web3.eth.getBalance(plotusNewAddress); - assert.equal(parseFloat(plotusBalanceAfter), 10000000000000000); - lotBalanceAfter = await plotusToken.balanceOf(openMarkets["_openMarkets"][0]); - assert.equal(parseFloat(web3.utils.fromWei(lotBalanceAfter)).toFixed(2), (832.5835).toFixed(2)); - // assert.equal(parseFloat(web3.utils.fromWei(String(parseFloat(lotBalanceAfter) - parseFloat(lotBalanceBefore)))).toFixed(2), (4.5835).toFixed(2)); - // commented by Parv (as asserts already added above) - // lotBalanceBefore = lotBalanceBefore / 1; - // lotBalanceAfter = lotBalanceAfter / 1; - // console.log(`plotus eth balance before commision : ${plotusBalanceBefore}`); - // console.log(`plotus balance after commision : ${plotusBalanceAfter}`); - // console.log(`Lot Balance of market before commision : ${lotBalanceBefore}`); - // console.log(`Lot Balance of market before commision : ${lotBalanceAfter}`); - // console.log(`Difference : ${lotBalanceAfter - lotBalanceBefore}`); - }); - - it("2.check total return for each user Prediction values in eth", async () => { - accounts = [user1, user2, user3, user4, user5, user6, user7, user8, user9, user10]; - options = [2, 2, 2, 3, 1, 1, 2, 3, 3, 2]; - getReturnsInEth = async (user) => { - // return userReturn in eth - const response = await marketInstance.getReturn(user); - let returnAmountInEth = web3.utils.fromWei(response[0][1]); - return returnAmountInEth; - }; - - const returnInEthExpected = [0, 0, 0, 0, 1.851161356, 5.141838644, 0.5994, 1.1988, 0.7992, 0.3996]; - // calulate rewards for every user in eth - - // console.log("Rewards in Eth"); - for (let index = 0; index < 10; index++) { - // check eth returns - let returns = await getReturnsInEth(accounts[index]); - assert.equal(parseFloat(returns).toFixed(2), returnInEthExpected[index].toFixed(2)); - // commented by Parv (as assert already added above) - // console.log(`return : ${returns} Expected :${returnInEthExpected[index]}`); - } - }); - it("3.Check User Recived The appropriate amount", async () => { - accounts = [user1, user2, user3, user4, user5, user6, user7, user8, user9, user10]; - const totalReturnLotExpexted = [79.96, 0, 125.937, 0, 133.6431475, 493.0463525, 0, 0, 0, 0]; - const returnInEthExpected = [0, 0, 0, 0, 1.851161356, 5.141838644, 0.5994, 1.1988, 0.7992, 0.3996]; - for (let account of accounts) { - beforeClaim = await web3.eth.getBalance(account); - beforeClaimToken = await plotusToken.balanceOf(account); - await marketInstance.claimReturn(account); - afterClaim = await web3.eth.getBalance(account); - afterClaimToken = await plotusToken.balanceOf(account); - diff = afterClaim - beforeClaim; - diff = new BigNumber(diff); - conv = new BigNumber(1000000000000000000); - diff = diff / conv; - diff = diff.toFixed(2); - // expectedInEth = returnInEthExpected[accounts.indexOf(account)].toFixed(2); - // assert.equal(diff, expectedInEth); - - diffToken = afterClaimToken - beforeClaimToken; - diffToken = diffToken / conv; - diffToken = diffToken.toFixed(2); - expectedInLot = totalReturnLotExpexted[accounts.indexOf(account)].toFixed(2); - assert.equal(diffToken, expectedInLot); - - // commented by Parv (as assert already added above) - // console.log(`User ${accounts.indexOf(account) + 1}`); - // console.log(`Returned in Eth : ${diff} Expected : ${expectedInEth} `); - // console.log(`Returned in Lot : ${diffToken} Expected : ${expectedInLot} `); - } - }); -}); -contract("Market", async function([user1, user2]) { - let masterInstance, BLOTInstance; - it("Test BLOT Contract", async () => { - masterInstance = await OwnedUpgradeabilityProxy.deployed(); - masterInstance = await Master.at(masterInstance.address); - plotusToken = await PlotusToken.deployed(); - BLOTInstance = await BLOT.at(await masterInstance.getLatestAddress(web3.utils.toHex("BL"))); - MockUniswapRouterInstance = await MockUniswapRouter.deployed(); - plotusNewAddress = await masterInstance.getLatestAddress(web3.utils.toHex("PL")); - plotusNewInstance = await Plotus.at(plotusNewAddress); - marketConfig = await plotusNewInstance.marketUtility(); - marketConfig = await MarketConfig.at(marketConfig); - - - let isMinter = await BLOTInstance.isMinter(user1); - - assert.equal(isMinter, true); - - isMinter = await BLOTInstance.isMinter(user2); - assert.equal(isMinter, false); - receipt = await BLOTInstance.addMinter(user2); - isMinter = await BLOTInstance.isMinter(user2); - assert.equal(isMinter, true); - assert.equal(receipt.logs[0].event, "MinterAdded"); - assert.equal(receipt.logs[0].args.account, user2); - - receipt = await BLOTInstance.renounceMinter({ from: user2 }); - isMinter = await BLOTInstance.isMinter(user2); - assert.equal(isMinter, false); - assert.equal(receipt.logs[0].event, "MinterRemoved"); - assert.equal(receipt.logs[0].args.account, user2); - - await assertRevert(BLOTInstance.mint(user2, 100)); - try { - await BLOTInstance.transfer("0x0000000000000000000000000000000000000000", 10, { from: user1 }); - assert.fail(); - } catch (e) {} - }); -}); - -contract("More cases for airdrop", async function([user1, user2]) { - it("Should Revert if deployed with null address as plot token, blot token", async () => { - let endDate = (await latestTime())/1+(24*3600); - await assertRevert(Airdrop.new(nullAddress, user1, endDate, toWei(10))); - await assertRevert(Airdrop.new(user1, nullAddress, endDate, toWei(10))); - }); - it("Should Revert if deployed with past time as end date", async () => { - let endDate = (await latestTime())/1-(24); - await assertRevert(Airdrop.new(user1, user1, endDate, toWei(10))); - }); - it("Should Revert if non owner calls airdropBLot, user array have different length than amount array", async () => { - let endDate = (await latestTime())/1+(24*3600); - let _airdrop = await Airdrop.new(plotusToken.address, BLOTInstance.address, endDate, toWei(100)); - await assertRevert(_airdrop.airdropBLot([],[],{from:user2})); - await assertRevert(_airdrop.airdropBLot([user1,user2],[toWei(10)])); - }); - it("Should Revert if tries to allocate after end date, null address in user list, 0 amount in amount list", async () => { - let endDate = (await latestTime())/1+(24*3600); - let _airdrop = await Airdrop.new(plotusToken.address, BLOTInstance.address, endDate, toWei(10)); - await assertRevert(_airdrop.airdropBLot([nullAddress],[toWei(10)])); - await assertRevert(_airdrop.airdropBLot([user1],[0])); - await increaseTime(24*3600); - await assertRevert(_airdrop.airdropBLot([user1],[toWei(10)])); - }); - it("Should Revert if tries to allocate multiple times to same user, non owner tries to call takeLeftOverPlot, tries to call takeLeftOverPlot before end date", async () => { - let endDate = (await latestTime())/1+(24*3600); - let _airdrop = await Airdrop.new(plotusToken.address, BLOTInstance.address, endDate, toWei(100)); - await assertRevert(_airdrop.takeLeftOverPlot()); - await assertRevert(_airdrop.takeLeftOverPlot({from:user2})); - await _airdrop.airdropBLot([user1],[toWei(10)]); - await assertRevert(_airdrop.airdropBLot([user1],[toWei(10)])); - }); - it("Should Revert if tries to claim after end date, user can not claim multiple time", async () => { - let endDate = (await latestTime())/1+(24*3600); - let _airdrop = await Airdrop.new(plotusToken.address, BLOTInstance.address, endDate, toWei(100)); - await _airdrop.airdropBLot([user1],[toWei(10)]); - await plotusToken.transfer(_airdrop.address, toWei(30)); - await BLOTInstance.addMinter(_airdrop.address); - await _airdrop.claim({from:user1}); - await assertRevert(_airdrop.claim({from:user1})); - await increaseTime(24*3600); - await assertRevert(_airdrop.claim({from:user1})); - }); - it("Should be able to take back plot toekens after end date", async () => { - let endDate = (await latestTime())/1+(24*3600); - let _airdrop = await Airdrop.new(plotusToken.address, BLOTInstance.address, endDate, toWei(100)); - await plotusToken.transfer(_airdrop.address, toWei(30)); - await increaseTime(24*3600); - await _airdrop.takeLeftOverPlot(); - assert.equal(await plotusToken.balanceOf(_airdrop.address), 0); - }); - it("Owner should be able to transfer ownership to other address", async () => { - let endDate = (await latestTime())/1+(24*3600); - let _airdrop = await Airdrop.new(plotusToken.address, BLOTInstance.address, endDate, toWei(100)); - assert.equal(await _airdrop.owner(), user1); - await _airdrop.tranferOwnership(user2); - assert.equal(await _airdrop.owner(), user2); - }); - it("Should revert if tries to transfer ownership to null address", async () => { - let endDate = (await latestTime())/1+(24*3600); - let _airdrop = await Airdrop.new(plotusToken.address, BLOTInstance.address, endDate, toWei(100)); - await assertRevert(_airdrop.tranferOwnership(nullAddress)); - }); - it("Should revert if tries to allocate more than budget", async () => { - let endDate = (await latestTime())/1+(24*3600); - let _airdrop = await Airdrop.new(plotusToken.address, BLOTInstance.address, endDate, toWei(100)); - await _airdrop.airdropBLot([user1],[toWei(50)]); - await assertRevert(_airdrop.airdropBLot([user2],[toWei(51)])); - }); -}); diff --git a/test/03_BasicGovernance.test.js b/test/03_BasicGovernance.test.js deleted file mode 100644 index b1fc04e72..000000000 --- a/test/03_BasicGovernance.test.js +++ /dev/null @@ -1,330 +0,0 @@ -const OwnedUpgradeabilityProxy = artifacts.require('OwnedUpgradeabilityProxy'); -const Governance = artifacts.require("Governance"); -const MemberRoles = artifacts.require("MockMemberRoles"); -const ProposalCategory = artifacts.require("ProposalCategory"); -const TokenController = artifacts.require("TokenController"); -const Master = artifacts.require("Master"); -const PlotusToken = artifacts.require("MockPLOT"); -const assertRevert = require("./utils/assertRevert.js").assertRevert; -const increaseTime = require("./utils/increaseTime.js").increaseTime; -const encode = require("./utils/encoder.js").encode; -const { toHex, toWei } = require("./utils/ethTools.js"); -const expectEvent = require("./utils/expectEvent"); -const gvProp = require("./utils/gvProposal.js").gvProposal; -const Web3 = require("web3"); -const { assert } = require("chai"); -const gvProposalWithIncentive = require("./utils/gvProposal.js").gvProposalWithIncentive; -const gvProposalWithIncentiveViaTokenHolder = require("./utils/gvProposal.js").gvProposalWithIncentiveViaTokenHolder; -const web3 = new Web3(); -const AdvisoryBoard = "0x41420000"; -let maxAllowance = "115792089237316195423570985008687907853269984665640564039457584007913129639935"; - -let gv; -let cr; -let pc; -let nxms; -let proposalId; -let pId; -let mr; -let plotusToken; -let tc; -let td; - -contract("Governance", ([ab1, ab2, ab3, ab4, mem1, mem2, mem3, mem4, mem5, mem6, mem7, notMember, dr1, dr2, dr3]) => { - before(async function () { - nxms = await OwnedUpgradeabilityProxy.deployed(); - nxms = await Master.at(nxms.address); - plotusToken = await PlotusToken.deployed(); - let address = await nxms.getLatestAddress(toHex("GV")); - gv = await Governance.at(address); - address = await nxms.getLatestAddress(toHex("PC")); - pc = await ProposalCategory.at(address); - address = await nxms.getLatestAddress(toHex("MR")); - mr = await MemberRoles.at(address); - tc = await TokenController.at(await nxms.getLatestAddress(toHex("MR"))); - }); - - it("15.1 Should be able to change tokenHoldingTime manually", async function () { - await assertRevert(gv.updateUintParameters(toHex("GOVHOLD"), 3000)); - }); - - it("15.2 Only Advisory Board members are authorized to categorize proposal", async function () { - let allowedToCategorize = await gv.allowedToCatgorize(); - assert.equal(allowedToCategorize.toNumber(), 1); - }); - - it("15.3 Should not allow unauthorized to change master address", async function () { - await assertRevert(gv.setMasterAddress({ from: notMember })); - // await gv.changeDependentContractAddress(); - }); - - it("15.4 Should not allow unauthorized to create proposal", async function () { - await assertRevert( - gv.createProposal("Proposal", "Description", "Hash", 0, { - from: notMember, - }) - ); - await assertRevert( - gv.createProposalwithSolution("Add new member", "Add new member", "hash", 9, "", "0x", { from: notMember }) - ); - }); - - it("15.5 Should create a proposal", async function () { - let propLength = await gv.getProposalLength(); - proposalId = propLength.toNumber(); - await gv.createProposal("Proposal1", "Proposal1", "Proposal1", 0); //Pid 1 - let propLength2 = await gv.getProposalLength(); - assert.isAbove(propLength2.toNumber(), propLength.toNumber(), "Proposal not created"); - }); - - it("15.6 Should not allow unauthorized person to categorize proposal", async function () { - await assertRevert(gv.categorizeProposal(proposalId, 1, 0, { from: notMember })); - }); - - it("15.7 Should not categorize under invalid category", async function () { - await assertRevert(gv.categorizeProposal(proposalId, 0, 0)); - await assertRevert(gv.categorizeProposal(proposalId, 35, 0)); - }); - - it("Should not open proposal for voting before categorizing", async () => { - await assertRevert(gv.submitProposalWithSolution(proposalId, "Addnewmember", "0x4d52")); - }); - - it("Should categorize proposal", async function () { - assert.equal(await mr.checkRole(ab1, 1), 1); - await gv.categorizeProposal(proposalId, 2, 0); - let proposalData = await gv.proposal(proposalId); - assert.equal(proposalData[1].toNumber(), 2, "Proposal not categorized"); - }); - - it("Should allow only owner to open proposal for voting", async () => { - // await gv.categorizeProposal(proposalId, 2, 0); - await gv.proposal(proposalId); - await pc.category(9); - await assertRevert(gv.submitVote(proposalId, 1)); - await assertRevert( - gv.submitProposalWithSolution( - proposalId, - "Addnewmember", - "0xffa3992900000000000000000000000000000000000000000000000000000000000000004344000000000000000000000000000000000000000000000000000000000000", - { from: notMember } - ) - ); - await gv.submitProposalWithSolution( - proposalId, - "Addnewmember", - "0xffa3992900000000000000000000000000000000000000000000000000000000000000004344000000000000000000000000000000000000000000000000000000000000" - ); - assert.equal((await gv.canCloseProposal(proposalId)).toNumber(), 0); - }); - - it("15.13 Should not categorize proposal if solution exists", async function () { - await assertRevert(gv.categorizeProposal(proposalId, 2, toWei(1))); - }); - - it("15.14 Should not allow voting for non existent solution", async () => { - await assertRevert(gv.submitVote(proposalId, 5)); - }); - - it("15.15 Should not allow unauthorized people to vote", async () => { - await assertRevert(gv.submitVote(proposalId, 1, { from: notMember })); - }); - - it("15.16 Should submit vote to valid solution", async function () { - await gv.submitVote(proposalId, 1); - await gv.proposalDetails(proposalId); - await assertRevert(gv.submitVote(proposalId, 1)); - }); - - it('15.17 Should not transfer tokens if voted on governance', async function() { - await assertRevert(plotusToken.transfer(mem1, toWei(100))); - await assertRevert(plotusToken.transferFrom(ab1, mem1, toWei(100), {from: mem1})); - }); - - it("15.18 Should close proposal", async function () { - let canClose = await gv.canCloseProposal(proposalId); - assert.equal(canClose.toNumber(), 1); - await gv.closeProposal(proposalId); - }); - - it("15.19 Should not close already closed proposal", async function () { - let canClose = await gv.canCloseProposal(proposalId); - assert.equal(canClose.toNumber(), 2); - await assertRevert(gv.closeProposal(proposalId)); - }); - - it("15.20 Should get rewards", async function () { - let pendingRewards = await gv.getPendingReward(ab1); - }); - - it("15.22 Should claim rewards", async function () { - await gv.claimReward(ab1, 20); - let pendingRewards = await gv.getPendingReward(ab1); - assert.equal(pendingRewards.toNumber(), 0, "Rewards not claimed"); - pId = await gv.getProposalLength(); - lastClaimed = await gv.lastRewardClaimed(ab1); - pendingRewards = await gv.getPendingReward(ab1); - }); - - // it('15.23 Should not claim reward twice for same proposal', async function() { - // await assertRevert(cr.claimAllPendingReward(20)); - // }); - - it("Should claim rewards for multiple number of proposals", async function () { - let action = "updateUintParameters(bytes8,uint)"; - let code = "MAXFOL"; - let proposedValue = 50; - let lastClaimed = await gv.lastRewardClaimed(ab1); - let actionHash = encode(action, code, proposedValue); - lastClaimed = await gv.lastRewardClaimed(ab1); - proposalId = await gv.getProposalLength(); - for (let i = 0; i < 3; i++) { - pId = await gv.getProposalLength(); - await gv.createProposal("Proposal1", "Proposal1", "Proposal1", 0); //Pid 1 - await gv.categorizeProposal(pId, 2, toWei(1)); - await gv.submitProposalWithSolution( - pId, - "Addnewmember", - "0xffa3992900000000000000000000000000000000000000000000000000000000000000004344000000000000000000000000000000000000000000000000000000000000" - ); - await gv.submitVote(pId,1); - - // await gvProposalWithIncentiveViaTokenHolder(12, actionHash, mr, gv, 2, 10); - } - let pendingRewards = await gv.getPendingReward(ab1); - await gv.claimReward(ab1, 20); - pendingRewards = await gv.getPendingReward(ab1); - pId = await gv.getProposalLength(); - lastClaimed = await gv.lastRewardClaimed(ab1); - }); - - it("Claim rewards for proposals which are not in sequence", async function () { - pId = await gv.getProposalLength(); - let action = "updateUintParameters(bytes8,uint)"; - let code = "MAXFOL"; - let proposedValue = 50; - let actionHash = encode(action, code, proposedValue); - for (let i = 0; i < 3; i++) { - await gvProposalWithIncentiveViaTokenHolder(12, actionHash, mr, gv, 2, 10); - } - let p = await gv.getProposalLength(); - await assertRevert(gv.rejectAction(pId)); - await gv.createProposal("proposal", "proposal", "proposal", 0); - await gv.categorizeProposal(p, 12, 10); - await gv.submitProposalWithSolution(p, "proposal", actionHash); - await gv.submitVote(p, 1); - for (let i = 0; i < 3; i++) { - await gvProposalWithIncentiveViaTokenHolder(12, actionHash, mr, gv, 2, 10); - } - let pendingRewards = await gv.getPendingReward(ab1); - await gv.claimReward(ab1, 20); - pendingRewards = await gv.getPendingReward(ab1); - - let p1 = await gv.getProposalLength(); - let lastClaimed = await gv.lastRewardClaimed(ab1); - assert.equal(lastClaimed.toNumber(), proposalId.toNumber() - 1); - await gv.closeProposal(p); - pendingRewards = await gv.getPendingReward(ab1); - await gv.claimReward(ab1, 20); - pendingRewards = await gv.getPendingReward(ab1); - - lastClaimed = await gv.lastRewardClaimed(ab1); - assert.equal(lastClaimed.toNumber(), proposalId.toNumber() - 1); - }); - - it("Claim Rewards for maximum of 20 proposals", async function () { - pendingRewards = await gv.getPendingReward(ab1); - await gv.claimReward(ab1, 20); - let actionHash = encode("updateUintParameters(bytes8,uint)", "MAXFOL", 50); - let p1 = await gv.getProposalLength(); - let lastClaimed = await gv.lastRewardClaimed(ab1); - for (let i = 0; i < 7; i++) { - await gvProposalWithIncentiveViaTokenHolder(12, actionHash, mr, gv, 2, 10); - } - await assertRevert(gv.rejectAction(lastClaimed/1 + 1, {from: ab1})); - await gv.closeProposal(lastClaimed/1 + 1); - await gv.closeProposal(lastClaimed/1 + 2); - await gv.closeProposal(lastClaimed/1 + 3); - await gv.claimReward(ab1, 20); - pendingRewards = await gv.getPendingReward(ab1); - p1 = await gv.getProposalLength(); - let lastProposal = p1.toNumber() - 1; - lastClaimed = await gv.lastRewardClaimed(ab1); - assert.equal(lastClaimed.toNumber(), lastProposal); - }); - - it("Proposal should be closed if not categorized for more than 14 days", async function () { - pId = await gv.getProposalLength(); - await gv.createProposal("Proposal", "Proposal", "Proposal", 0); - await increaseTime(604810 * 2); - await gv.closeProposal(pId); - }); - - it("Proposal should be closed if not submitted to vote for more than 14 days", async function () { - pId = await gv.getProposalLength(); - await gv.createProposal("Proposal", "Proposal", "Proposal", 0); - await gv.categorizeProposal(pId, 12, 10); - await increaseTime(604810 * 2); - await gv.closeProposal(pId); - }); - - it("Should add initial AB members and create a proposal", async function() { - await increaseTime(604800*2); - await plotusToken.transfer(ab2, toWei(100)); - await plotusToken.transfer(ab3, toWei(100)); - await plotusToken.transfer(ab4, toWei(100)); - await mr.addInitialABMembers([ab2, ab3, ab4]); - let actionHash = encode("updateUintParameters(bytes8,uint)", "ACWT", 1); - pId = await gv.getProposalLength(); - await gv.createProposal("proposal", "proposal", "proposal", 0); - await gv.categorizeProposal(pId, 13, 10); - await gv.submitProposalWithSolution(pId, "proposal", actionHash); - await gv.submitVote(pId, 1); - await gv.submitVote(pId, 1, {from:ab2}); - await gv.submitVote(pId, 1, {from:ab3}); - await gv.submitVote(pId, 1, {from:ab4}); - await increaseTime(604810); - await gv.closeProposal(pId); - }); - - it("Should reject action with AB", async function() { - await gv.rejectAction(pId); - }); - - it("Should not allow same AB reject action twice", async function() { - await assertRevert(gv.rejectAction(pId, {from: ab1})); - }); - - it("Should reject action if 60% of ab rejects proposal", async function() { - await gv.rejectAction(pId, {from: ab2}); - await gv.rejectAction(pId, {from: ab3}); - assert.equal(await gv.proposalActionStatus(pId), 2); - }); - - it("Should not reject action if already rejected", async function() { - await assertRevert(gv.rejectAction(pId, {from: ab3})); - }); - - it("Should not trigger action if already rejected", async function() { - await assertRevert(gv.triggerAction(pId)); - }); - - it("Should consider AB vote if quorum is not reached", async function() { - await increaseTime(604800*2); - let actionHash = encode("updateUintParameters(bytes8,uint)", "ACWT", 50); - pId = await gv.getProposalLength(); - await gv.createProposal("proposal", "proposal", "proposal", 0); - await gv.categorizeProposal(pId, 13, 10); - await gv.submitProposalWithSolution(pId, "proposal", actionHash); - await gv.submitVote(pId, 1, {from:ab2}); - await gv.submitVote(pId, 1, {from:ab3}); - await gv.submitVote(pId, 1, {from:ab4}); - await increaseTime(604810); - await gv.closeProposal(pId); - let proposalData = await gv.proposal(pId); - assert.equal(proposalData[2]/1,3); - await increaseTime(604800); - await gv.triggerAction(pId); - }); - -}); diff --git a/test/03_BasicGovernanceNewMetaTx.test.js b/test/03_BasicGovernanceNewMetaTx.test.js new file mode 100644 index 000000000..904fbcd58 --- /dev/null +++ b/test/03_BasicGovernanceNewMetaTx.test.js @@ -0,0 +1,676 @@ +const OwnedUpgradeabilityProxy = artifacts.require('OwnedUpgradeabilityProxy'); +const Governance = artifacts.require("Governance"); +const AllMarkets = artifacts.require("AllMarkets"); +const MemberRoles = artifacts.require("MockMemberRoles"); +const ProposalCategory = artifacts.require("ProposalCategory"); +const TokenController = artifacts.require("TokenController"); +const Master = artifacts.require("Master"); +const PlotusToken = artifacts.require("MockPLOT"); +const assertRevert = require("./utils/assertRevert.js").assertRevert; +const increaseTime = require("./utils/increaseTime.js").increaseTime; +const encode = require("./utils/encoder.js").encode; +const encode1 = require("./utils/encoder.js").encode1; +const encode3 = require("./utils/encoder.js").encode3; +const { toHex, toWei } = require("./utils/ethTools.js"); +const expectEvent = require("./utils/expectEvent"); +const gvProp = require("./utils/gvProposal.js").gvProposal; +const Web3 = require("web3"); +const { assert } = require("chai"); +const gvProposalWithIncentive = require("./utils/gvProposal.js").gvProposalWithIncentive; +const gvProposalWithIncentiveViaTokenHolderMetaTX = require("./utils/gvProposal.js").gvProposalWithIncentiveViaTokenHolderMetaTX; +const signAndExecuteMetaTx = require("./utils/signAndExecuteMetaTx.js").signAndExecuteMetaTx; +const web3 = new Web3(); +const AdvisoryBoard = "0x41420000"; +let maxAllowance = "115792089237316195423570985008687907853269984665640564039457584007913129639935"; +let privateKeyList = ["fb437e3e01939d9d4fef43138249f23dc1d0852e69b0b5d1647c087f869fabbd","7c85a1f1da3120c941b83d71a154199ee763307683f206b98ad92c3b4e0af13e","ecc9b35bf13bd5459350da564646d05c5664a7476fe5acdf1305440f88ed784c","f4470c3fca4dbef1b2488d016fae25978effc586a1f83cb29ac8cb6ab5bc2d50","141319b1a84827e1046e93741bf8a9a15a916d49684ab04925ac4ce4573eea23","d54b606094287758dcf19064a8d91c727346aadaa9388732e73c4315b7c606f9","49030e42ce4152e715a7ddaa10e592f8e61d00f70ef11f48546711f159d985df","b96761b1e7ebd1e8464a78a98fe52f53ce6035c32b4b2b12307a629a551ff7cf","d4786e2581571c863c7d12231c3afb6d4cef390c0ac9a24b243293721d28ea95","ed28e3d3530544f1cf2b43d1956b7bd13b63c612d963a8fb37387aa1a5e11460","05b127365cf115d4978a7997ee98f9b48f0ddc552b981c18aa2ee1b3e6df42c6","9d11dd6843f298b01b34bd7f7e4b1037489871531d14b58199b7cba1ac0841e6","f79e90fa4091de4fc2ec70f5bf67b24393285c112658e0d810e6bd711387fbb9","99f1fc0f09230ce745b6a256ba7082e6e51a2907abda3d9e735a5c8188bb4ba1","477f86cce983b9c91a36fdcd4a7ce21144a08dee9b1aafb91b9c70e57f717ce6","b03d2e6bb4a7d71c66a66ff9e9c93549cae4b593f634a4ea2a1f79f94200f5b4","9ddc0f53a81e631dcf39d5155f41ec12ed551b731efc3224f410667ba07b37dc","cf087ff9ae7c9954ad8612d071e5cdf34a6024ee1ae477217639e63a802a53dd","b64f62b94babb82cc78d3d1308631ae221552bb595202fc1d267e1c29ce7ba60","a91e24875f8a534497459e5ccb872c4438be3130d8d74b7e1104c5f94cdcf8c2","4f49f3d029eeeb3fed14d59625acd088b6b34f3b41c527afa09d29e4a7725c32","179795fd7ac7e7efcba3c36d539a1e8659fb40d77d0a3fab2c25562d99793086","4ba37d0b40b879eceaaca2802a1635f2e6d86d5c31e3ff2d2fd13e68dd2a6d3d","6b7f5dfba9cd3108f1410b56f6a84188eee23ab48a3621b209a67eea64293394","870c540da9fafde331a3316cee50c17ad76ddb9160b78b317bef2e6f6fc4bac0","470b4cccaea895d8a5820aed088357e380d66b8e7510f0a1ea9b575850160241","8a55f8942af0aec1e0df3ab328b974a7888ffd60ded48cc6862013da0f41afbc","2e51e8409f28baf93e665df2a9d646a1bf9ac8703cbf9a6766cfdefa249d5780","99ef1a23e95910287d39493d8d9d7d1f0b498286f2b1fdbc0b01495f10cf0958","6652200c53a4551efe2a7541072d817562812003f9d9ef0ec17995aa232378f8","39c6c01194df72dda97da2072335c38231ced9b39afa280452afcca901e73643","12097e411d948f77b7b6fa4656c6573481c1b4e2864c1fca9d5b296096707c45","cbe53bf1976aee6cec830a848c6ac132def1503cffde82ccfe5bd15e75cbaa72","eeab5dcfff92dbabb7e285445aba47bd5135a4a3502df59ac546847aeb5a964f","5ea8279a578027abefab9c17cef186cccf000306685e5f2ee78bdf62cae568dd","0607767d89ad9c7686dbb01b37248290b2fa7364b2bf37d86afd51b88756fe66","e4fd5f45c08b52dae40f4cdff45e8681e76b5af5761356c4caed4ca750dc65cd","145b1c82caa2a6d703108444a5cf03e9cb8c3cd3f19299582a564276dbbba734","736b22ec91ae9b4b2b15e8d8c220f6c152d4f2228f6d46c16e6a9b98b4733120","ac776cb8b40f92cdd307b16b83e18eeb1fbaa5b5d6bd992b3fda0b4d6de8524c","65ba30e2202fdf6f37da0f7cfe31dfb5308c9209885aaf4cef4d572fd14e2903","54e8389455ec2252de063e83d3ce72529d674e6d2dc2070661f01d4f76b63475","fbbbfb525dd0255ee332d51f59648265aaa20c2e9eff007765cf4d4a6940a849","8de5e418f34d04f6ea947ce31852092a24a705862e6b810ca9f83c2d5f9cda4d","ea6040989964f012fd3a92a3170891f5f155430b8bbfa4976cde8d11513b62d9","14d94547b5deca767137fbd14dae73e888f3516c742fad18b83be333b38f0b88","47f05203f6368d56158cda2e79167777fc9dcb0c671ef3aabc205a1636c26a29"]; + +let gv; +let cr; +let pc; +let nxms; +let proposalId; +let pId; +let mr; +let plotusToken; +let tc; +let td, allMarkets; + +contract("Governance", ([ab1, ab2, ab3, ab4, mem1, mem2, mem3, mem4, mem5, mem6, mem7, notMember, dr1, dr2, dr3]) => { + before(async function () { + nxms = await OwnedUpgradeabilityProxy.deployed(); + nxms = await Master.at(nxms.address); + plotusToken = await PlotusToken.deployed(); + let address = await nxms.getLatestAddress(toHex("GV")); + gv = await Governance.at(address); + address = await nxms.getLatestAddress(toHex("PC")); + pc = await ProposalCategory.at(address); + address = await nxms.getLatestAddress(toHex("MR")); + mr = await MemberRoles.at(address); + tc = await TokenController.at(await nxms.getLatestAddress(toHex("MR"))); + allMarkets = await AllMarkets.at(await nxms.getLatestAddress(toHex("MC"))); + await plotusToken.transfer(allMarkets.address, toWei(10000)); + await increaseTime(604800); + }); + + it("15.1 Should be able to change tokenHoldingTime manually", async function () { + let functionSignature = encode3("updateUintParameters(bytes8,uint256)",toHex("GOVHOLD"), 3000); + await assertRevert(signAndExecuteMetaTx( + privateKeyList[0], + ab1, + functionSignature, + gv, + "GV" + )); + functionSignature = encode3("updateUintParameters(bytes8,uint256)",toHex("GOVHOLD"), 3000); + functionSignature = functionSignature + (gv.address).slice(2); + await assertRevert(signAndExecuteMetaTx( + privateKeyList[0], + ab1, + functionSignature, + gv, + "GV" + )); + }); + + it("15.2 Only Advisory Board members are authorized to categorize proposal", async function () { + let allowedToCategorize = await gv.allowedToCatgorize(); + assert.equal(allowedToCategorize.toNumber(), 1); + }); + + it("15.3 Should not allow unauthorized to change master address", async function () { + let functionSignature = encode3("setMasterAddress()"); + await assertRevert(signAndExecuteMetaTx( + privateKeyList[11], + notMember, + functionSignature, + gv, + "GV" + )); + // await assertRevert(gv.setMasterAddress({ from: notMember })); + // await gv.changeDependentContractAddress(); + }); + + it("15.4 Should not allow unauthorized to create proposal", async function () { + let functionSignature = encode3("createProposal(string,string,string,uint256)","Proposal1", "Proposal1", "Proposal1", 0); + await assertRevert(signAndExecuteMetaTx( + privateKeyList[11], + notMember, + functionSignature, + gv, + "GV" + )); + functionSignature = encode3("createProposalwithSolution(string,string,string,uint256,string,bytes32)","Add new member", "Add new member", "hash", 9, "", "0x"); + await assertRevert(signAndExecuteMetaTx( + privateKeyList[11], + notMember, + functionSignature, + gv, + "GV" + )); + // await assertRevert( + // gv.createProposalwithSolution("Add new member", "Add new member", "hash", 9, "", "0x", { from: notMember }) + // ); + }); + + it("15.5 Should create a proposal", async function () { + let propLength = await gv.getProposalLength(); + proposalId = propLength.toNumber(); + // await gv.createProposal("Proposal1", "Proposal1", "Proposal1", 0); //Pid 1 + let functionSignature = encode3("createProposal(string,string,string,uint256)","Proposal1", "Proposal1", "Proposal1", 0); + await signAndExecuteMetaTx( + privateKeyList[0], + ab1, + functionSignature, + gv, + "GV" + ); + let propLength2 = await gv.getProposalLength(); + assert.isAbove(propLength2.toNumber(), propLength.toNumber(), "Proposal not created"); + }); + + it("15.6 Should not allow unauthorized person to categorize proposal", async function () { + // await assertRevert(gv.categorizeProposal(proposalId, 1, 0, { from: notMember })); + let functionSignature = encode3("categorizeProposal(uint256,uint256,uint256)",proposalId, 1, 0); + await assertRevert(signAndExecuteMetaTx( + privateKeyList[11], + notMember, + functionSignature, + gv, + "GV" + )); + }); + + it("15.7 Should not categorize under invalid category", async function () { + let functionSignature = encode3("categorizeProposal(uint256,uint256,uint256)",proposalId, 0, 0); + await assertRevert(signAndExecuteMetaTx( + privateKeyList[0], + ab1, + functionSignature, + gv, + "GV" + )); + functionSignature = encode3("categorizeProposal(uint256,uint256,uint256)",proposalId, 35, 0); + await assertRevert(signAndExecuteMetaTx( + privateKeyList[0], + ab1, + functionSignature, + gv, + "GV" + )); + // await assertRevert(gv.categorizeProposal(proposalId, 0, 0)); + // await assertRevert(gv.categorizeProposal(proposalId, 35, 0)); + }); + + it("Should not open proposal for voting before categorizing", async () => { + let functionSignature = encode3("submitProposalWithSolution(uint256,string,bytes)", proposalId, "", "0x4d52"); + await assertRevert(signAndExecuteMetaTx( + privateKeyList[0], + ab1, + functionSignature, + gv, + "GV" + )); + // await assertRevert(gv.submitProposalWithSolution(proposalId, "Addnewmember", "0x4d52")); + }); + + it("Should categorize proposal", async function () { + assert.equal(await mr.checkRole(ab1, 1), 1); + let functionSignature = encode3("categorizeProposal(uint256,uint256,uint256)",proposalId, 2, 0); + await signAndExecuteMetaTx( + privateKeyList[0], + ab1, + functionSignature, + gv, + "GV" + ); + // await gv.categorizeProposal(proposalId, 2, 0); + let proposalData = await gv.proposal(proposalId); + assert.equal(proposalData[1].toNumber(), 2, "Proposal not categorized"); + }); + + it("Should allow only owner to open proposal for voting", async () => { + // await gv.categorizeProposal(proposalId, 2, 0); + await gv.proposal(proposalId); + await pc.category(9); + let functionSignature = encode3("submitVote(uint256,uint256)",proposalId, 1); + await assertRevert(signAndExecuteMetaTx( + privateKeyList[0], + ab1, + functionSignature, + gv, + "GV" + )); + // await assertRevert(gv.submitVote(proposalId, 1)); + functionSignature = encode3("submitProposalWithSolution(uint256,string,bytes)", proposalId, "Addnewmember", "0xffa3992900000000000000000000000000000000000000000000000000000000000000004344000000000000000000000000000000000000000000000000000000000000"); + await assertRevert(signAndExecuteMetaTx( + privateKeyList[11], + notMember, + functionSignature, + gv, + "GV" + )); + // await assertRevert( + // gv.submitProposalWithSolution( + // proposalId, + // "Addnewmember", + // "0xffa3992900000000000000000000000000000000000000000000000000000000000000004344000000000000000000000000000000000000000000000000000000000000", + // { from: notMember } + // ) + // ); + functionSignature = encode3("submitProposalWithSolution(uint256,string,bytes)", proposalId, "Addnewmember", "0xffa3992900000000000000000000000000000000000000000000000000000000000000004344000000000000000000000000000000000000000000000000000000000000"); + await signAndExecuteMetaTx( + privateKeyList[0], + ab1, + functionSignature, + gv, + "GV" + ); + // await gv.submitProposalWithSolution( + // proposalId, + // "Addnewmember", + // "0xffa3992900000000000000000000000000000000000000000000000000000000000000004344000000000000000000000000000000000000000000000000000000000000" + // ); + assert.equal((await gv.canCloseProposal(proposalId)).toNumber(), 0); + }); + + it("15.13 Should not categorize proposal if solution exists", async function () { + let functionSignature = encode3("categorizeProposal(uint256,uint256,uint256)",proposalId, 2, toWei(1)); + await assertRevert(signAndExecuteMetaTx( + privateKeyList[0], + ab1, + functionSignature, + gv, + "GV" + )); + // await assertRevert(gv.categorizeProposal(proposalId, 2, toWei(1))); + }); + + it("15.14 Should not allow voting for non existent solution", async () => { + let functionSignature = encode3("submitVote(uint256,uint256)",proposalId, 5); + await assertRevert(signAndExecuteMetaTx( + privateKeyList[0], + ab1, + functionSignature, + gv, + "GV" + )); + // await assertRevert(gv.submitVote(proposalId, 5)); + }); + + it("15.15 Should not allow unauthorized people to vote", async () => { + let functionSignature = encode3("submitVote(uint256,uint256)",proposalId, 1); + await assertRevert(signAndExecuteMetaTx( + privateKeyList[11], + notMember, + functionSignature, + gv, + "GV" + )); + await assertRevert(gv.submitVote(proposalId, 1, { from: notMember })); + }); + + it("15.16 Should submit vote to valid solution", async function () { + let functionSignature = encode3("submitVote(uint256,uint256)",proposalId, 1); + await signAndExecuteMetaTx( + privateKeyList[0], + ab1, + functionSignature, + gv, + "GV" + ); + // await gv.submitVote(proposalId, 1); + await gv.proposalDetails(proposalId); + functionSignature = encode3("submitVote(uint256,uint256)",proposalId, 1); + await assertRevert(signAndExecuteMetaTx( + privateKeyList[0], + ab1, + functionSignature, + gv, + "GV" + )); + // await assertRevert(gv.submitVote(proposalId, 1)); + }); + + it('15.17 Should not transfer tokens if voted on governance', async function() { + await assertRevert(plotusToken.transfer(mem1, toWei(100))); + await assertRevert(plotusToken.transferFrom(ab1, mem1, toWei(100), {from: mem1})); + }); + + it("15.18 Should close proposal", async function () { + let canClose = await gv.canCloseProposal(proposalId); + assert.equal(canClose.toNumber(), 1); + await gv.closeProposal(proposalId); + }); + + it("15.19 Should not close already closed proposal", async function () { + let canClose = await gv.canCloseProposal(proposalId); + assert.equal(canClose.toNumber(), 2); + await assertRevert(gv.closeProposal(proposalId)); + }); + + it("15.20 Should get rewards", async function () { + let pendingRewards = await gv.getPendingReward(ab1); + }); + + it("15.22 Should claim rewards", async function () { + await gv.claimReward(ab1, 20); + let pendingRewards = await gv.getPendingReward(ab1); + assert.equal(pendingRewards.toNumber(), 0, "Rewards not claimed"); + pId = await gv.getProposalLength(); + lastClaimed = await gv.lastRewardClaimed(ab1); + pendingRewards = await gv.getPendingReward(ab1); + }); + + // it('15.23 Should not claim reward twice for same proposal', async function() { + // await assertRevert(cr.claimAllPendingReward(20)); + // }); + + it("Should claim rewards for multiple number of proposals", async function () { + let action = "updateUintParameters(bytes8,uint)"; + let code = "MAXFOL"; + let proposedValue = 50; + let lastClaimed = await gv.lastRewardClaimed(ab1); + let actionHash = encode(action, code, proposedValue); + lastClaimed = await gv.lastRewardClaimed(ab1); + proposalId = await gv.getProposalLength(); + for (let i = 0; i < 3; i++) { + pId = await gv.getProposalLength(); + let functionSignature = encode3("createProposal(string,string,string,uint256)","Proposal1", "Proposal1", "Proposal1", 0); + await signAndExecuteMetaTx( + privateKeyList[0], + ab1, + functionSignature, + gv, + "GV" + ); + // await gv.createProposal("Proposal1", "Proposal1", "Proposal1", 0); //Pid 1 + functionSignature = encode3("categorizeProposal(uint256,uint256,uint256)",pId, 2, toWei(1)); + await signAndExecuteMetaTx( + privateKeyList[0], + ab1, + functionSignature, + gv, + "GV" + ); + // await gv.categorizeProposal(pId, 2, toWei(1)); + functionSignature = encode3("submitProposalWithSolution(uint256,string,bytes)", pId, "Addnewmember", "0xffa3992900000000000000000000000000000000000000000000000000000000000000004344000000000000000000000000000000000000000000000000000000000000"); + await signAndExecuteMetaTx( + privateKeyList[0], + ab1, + functionSignature, + gv, + "GV" + ); + // await gv.submitProposalWithSolution( + // pId, + // "Addnewmember", + // "0xffa3992900000000000000000000000000000000000000000000000000000000000000004344000000000000000000000000000000000000000000000000000000000000" + // ); + functionSignature = encode3("submitVote(uint256,uint256)",pId, 1); + await signAndExecuteMetaTx( + privateKeyList[0], + ab1, + functionSignature, + gv, + "GV" + ); + // await gv.submitVote(pId,1); + + // await gvProposalWithIncentiveViaTokenHolderMetaTX(12, actionHash, mr, gv, 2, 10, 0, ab1, privateKeyList[0]); + } + let pendingRewards = await gv.getPendingReward(ab1); + await gv.claimReward(ab1, 20); + pendingRewards = await gv.getPendingReward(ab1); + pId = await gv.getProposalLength(); + lastClaimed = await gv.lastRewardClaimed(ab1); + }); + + it("Claim rewards for proposals which are not in sequence", async function () { + pId = await gv.getProposalLength(); + let action = "updateUintParameters(bytes8,uint)"; + let code = "MAXFOL"; + let proposedValue = 50; + let actionHash = encode(action, code, proposedValue); + for (let i = 0; i < 3; i++) { + await gvProposalWithIncentiveViaTokenHolderMetaTX(12, actionHash, mr, gv, 2, 10, 0, ab1, privateKeyList[0]); + } + let p = await gv.getProposalLength(); + await assertRevert(gv.rejectAction(pId)); + let functionSignature = encode3("createProposal(string,string,string,uint256)","Proposal1", "Proposal1", "Proposal1", 0); + await signAndExecuteMetaTx( + privateKeyList[0], + ab1, + functionSignature, + gv, + "GV" + ); + // await gv.createProposal("proposal", "proposal", "proposal", 0); + functionSignature = encode3("categorizeProposal(uint256,uint256,uint256)",p, 12, 10); + await signAndExecuteMetaTx( + privateKeyList[0], + ab1, + functionSignature, + gv, + "GV" + ); + // await gv.categorizeProposal(p, 12, 10); + functionSignature = encode3("submitProposalWithSolution(uint256,string,bytes)", p, "Addnewmember", actionHash); + await signAndExecuteMetaTx( + privateKeyList[0], + ab1, + functionSignature, + gv, + "GV" + ); + // await gv.submitProposalWithSolution(p, "proposal", actionHash); + functionSignature = encode3("submitVote(uint256,uint256)",p, 1); + await signAndExecuteMetaTx( + privateKeyList[0], + ab1, + functionSignature, + gv, + "GV" + ); + // await gv.submitVote(p, 1); + for (let i = 0; i < 3; i++) { + await gvProposalWithIncentiveViaTokenHolderMetaTX(12, actionHash, mr, gv, 2, 10, 0, ab1, privateKeyList[0]); + } + let pendingRewards = await gv.getPendingReward(ab1); + await gv.claimReward(ab1, 20); + pendingRewards = await gv.getPendingReward(ab1); + + let p1 = await gv.getProposalLength(); + let lastClaimed = await gv.lastRewardClaimed(ab1); + assert.equal(lastClaimed.toNumber(), proposalId.toNumber() - 1); + await gv.closeProposal(p); + pendingRewards = await gv.getPendingReward(ab1); + await gv.claimReward(ab1, 20); + pendingRewards = await gv.getPendingReward(ab1); + + lastClaimed = await gv.lastRewardClaimed(ab1); + assert.equal(lastClaimed.toNumber(), proposalId.toNumber() - 1); + }); + + it("Claim Rewards for maximum of 20 proposals", async function () { + pendingRewards = await gv.getPendingReward(ab1); + await gv.claimReward(ab1, 20); + let actionHash = encode("updateUintParameters(bytes8,uint)", "MAXFOL", 50); + let p1 = await gv.getProposalLength(); + let lastClaimed = await gv.lastRewardClaimed(ab1); + for (let i = 0; i < 7; i++) { + await gvProposalWithIncentiveViaTokenHolderMetaTX(12, actionHash, mr, gv, 2, 10, 0, ab1, privateKeyList[0]); + } + await assertRevert(gv.rejectAction(lastClaimed/1 + 1, {from: ab1})); + await gv.closeProposal(lastClaimed/1 + 1); + await gv.closeProposal(lastClaimed/1 + 2); + await gv.closeProposal(lastClaimed/1 + 3); + await gv.claimReward(ab1, 20); + pendingRewards = await gv.getPendingReward(ab1); + p1 = await gv.getProposalLength(); + let lastProposal = p1.toNumber() - 1; + lastClaimed = await gv.lastRewardClaimed(ab1); + assert.equal(lastClaimed.toNumber(), lastProposal); + }); + + it("Proposal should be closed if not categorized for more than 14 days", async function () { + pId = await gv.getProposalLength(); + let functionSignature = encode3("createProposal(string,string,string,uint256)","Proposal1", "Proposal1", "Proposal1", 0); + await signAndExecuteMetaTx( + privateKeyList[0], + ab1, + functionSignature, + gv, + "GV" + ); + // await gv.createProposal("Proposal", "Proposal", "Proposal", 0); + await increaseTime(604810 * 2); + await gv.closeProposal(pId); + }); + + it("Proposal should be closed if not submitted to vote for more than 14 days", async function () { + pId = await gv.getProposalLength(); + let functionSignature = encode3("createProposal(string,string,string,uint256)","Proposal1", "Proposal1", "Proposal1", 0); + await signAndExecuteMetaTx( + privateKeyList[0], + ab1, + functionSignature, + gv, + "GV" + ); + // await gv.createProposal("Proposal", "Proposal", "Proposal", 0); + functionSignature = encode3("categorizeProposal(uint256,uint256,uint256)",pId, 12, 10); + await signAndExecuteMetaTx( + privateKeyList[0], + ab1, + functionSignature, + gv, + "GV" + ); + // await gv.categorizeProposal(pId, 12, 10); + await increaseTime(604810 * 2); + await gv.closeProposal(pId); + }); + + it("Should add initial AB members and create a proposal", async function() { + await increaseTime(604800*2); + await plotusToken.transfer(ab2, toWei(100)); + await plotusToken.transfer(ab3, toWei(100)); + await plotusToken.transfer(ab4, toWei(100)); + await mr.addInitialABMembers([ab2, ab3, ab4]); + let actionHash = encode("updateUintParameters(bytes8,uint)", "ACWT", 1); + pId = await gv.getProposalLength(); + let functionSignature = encode3("createProposal(string,string,string,uint256)","Proposal1", "Proposal1", "Proposal1", 0); + await signAndExecuteMetaTx( + privateKeyList[0], + ab1, + functionSignature, + gv, + "GV" + ); + // await gv.createProposal("proposal", "proposal", "proposal", 0); + functionSignature = encode3("categorizeProposal(uint256,uint256,uint256)",pId, 13, 10); + await signAndExecuteMetaTx( + privateKeyList[0], + ab1, + functionSignature, + gv, + "GV" + ); + // await gv.categorizeProposal(pId, 13, 10); + functionSignature = encode3("submitProposalWithSolution(uint256,string,bytes)", pId, "Addnewmember", actionHash); + await signAndExecuteMetaTx( + privateKeyList[0], + ab1, + functionSignature, + gv, + "GV" + ); + // await gv.submitProposalWithSolution(pId, "proposal", actionHash); + functionSignature = encode3("submitVote(uint256,uint256)",pId, 1); + await signAndExecuteMetaTx( + privateKeyList[0], + ab1, + functionSignature, + gv, + "GV" + ); + // await gv.submitVote(pId, 1); + functionSignature = encode3("submitVote(uint256,uint256)",pId, 1); + await signAndExecuteMetaTx( + privateKeyList[1], + ab2, + functionSignature, + gv, + "GV" + ); + // await gv.submitVote(pId, 1, {from:ab2}); + functionSignature = encode3("submitVote(uint256,uint256)",pId, 1); + await signAndExecuteMetaTx( + privateKeyList[2], + ab3, + functionSignature, + gv, + "GV" + ); + // await gv.submitVote(pId, 1, {from:ab3}); + functionSignature = encode3("submitVote(uint256,uint256)",pId, 1); + await signAndExecuteMetaTx( + privateKeyList[3], + ab4, + functionSignature, + gv, + "GV" + ); + // await gv.submitVote(pId, 1, {from:ab4}); + await increaseTime(604810); + await gv.closeProposal(pId); + }); + + // it("Should reject action with AB", async function() { + // await gv.rejectAction(pId); + // }); + + // it("Should not allow same AB reject action twice", async function() { + // await assertRevert(gv.rejectAction(pId, {from: ab1})); + // }); + + // it("Should reject action if 60% of ab rejects proposal", async function() { + // await gv.rejectAction(pId, {from: ab2}); + // await gv.rejectAction(pId, {from: ab3}); + // assert.equal(await gv.proposalActionStatus(pId), 2); + // }); + + // it("Should not reject action if already rejected", async function() { + // await assertRevert(gv.rejectAction(pId, {from: ab3})); + // }); + + // it("Should not trigger action if already rejected", async function() { + // await assertRevert(gv.triggerAction(pId)); + // }); + + it("Should consider AB vote if quorum is not reached", async function() { + await increaseTime(604800*2); + let actionHash = encode("updateUintParameters(bytes8,uint)", "ACWT", 50); + pId = await gv.getProposalLength(); + let functionSignature = encode3("createProposal(string,string,string,uint256)","Proposal1", "Proposal1", "Proposal1", 0); + await signAndExecuteMetaTx( + privateKeyList[0], + ab1, + functionSignature, + gv, + "GV" + ); + // await gv.createProposal("proposal", "proposal", "proposal", 0); + functionSignature = encode3("categorizeProposal(uint256,uint256,uint256)",pId, 13, 10); + await signAndExecuteMetaTx( + privateKeyList[0], + ab1, + functionSignature, + gv, + "GV" + ); + // await gv.categorizeProposal(pId, 13, 10); + functionSignature = encode3("submitProposalWithSolution(uint256,string,bytes)", pId, "Addnewmember", actionHash); + await signAndExecuteMetaTx( + privateKeyList[0], + ab1, + functionSignature, + gv, + "GV" + ); + // await gv.submitProposalWithSolution(pId, "proposal", actionHash); + functionSignature = encode3("submitVote(uint256,uint256)",pId, 1); + await signAndExecuteMetaTx( + privateKeyList[1], + ab2, + functionSignature, + gv, + "GV" + ); + // await gv.submitVote(pId, 1, {from:ab2}); + functionSignature = encode3("submitVote(uint256,uint256)",pId, 1); + await signAndExecuteMetaTx( + privateKeyList[2], + ab3, + functionSignature, + gv, + "GV" + ); + // await gv.submitVote(pId, 1, {from:ab3}); + functionSignature = encode3("submitVote(uint256,uint256)",pId, 1); + await signAndExecuteMetaTx( + privateKeyList[3], + ab4, + functionSignature, + gv, + "GV" + ); + // await gv.submitVote(pId, 1, {from:ab4}); + await increaseTime(604810); + await gv.closeProposal(pId); + let proposalData = await gv.proposal(pId); + assert.equal(proposalData[2]/1,3); + assert.equal(await gv.proposalActionStatus(pId), 3); + }); + +}); diff --git a/test/04_dailyMarketOptionPrice.js b/test/04_dailyMarketOptionPrice.js index 9e19affbb..16f1e9e23 100644 --- a/test/04_dailyMarketOptionPrice.js +++ b/test/04_dailyMarketOptionPrice.js @@ -1,513 +1,235 @@ const { assert } = require("chai"); const OwnedUpgradeabilityProxy = artifacts.require("OwnedUpgradeabilityProxy"); -const Market = artifacts.require("MockMarket"); -const Plotus = artifacts.require("MarketRegistry"); const Master = artifacts.require("Master"); -const PlotusToken = artifacts.require("MockPLOT"); -const MarketConfig = artifacts.require("MockConfig"); const TokenController = artifacts.require("TokenController"); +const PlotusToken = artifacts.require("MockPLOT"); const MockchainLinkBTC = artifacts.require("MockChainLinkAggregator"); +const MarketConfig = artifacts.require("MockConfig"); const BLOT = artifacts.require("BLOT"); -const web3 = Market.web3; +const AllMarkets = artifacts.require("AllMarkets"); const increaseTime = require("./utils/increaseTime.js").increaseTime; +const increaseTimeTo = require("./utils/increaseTime.js").increaseTimeTo; +const { encode, encode1,encode3 } = require("./utils/encoder.js"); +const signAndExecuteMetaTx = require("./utils/signAndExecuteMetaTx.js").signAndExecuteMetaTx; +const { toHex, toWei, toChecksumAddress } = require("./utils/ethTools"); +let privateKeyList = ["fb437e3e01939d9d4fef43138249f23dc1d0852e69b0b5d1647c087f869fabbd","7c85a1f1da3120c941b83d71a154199ee763307683f206b98ad92c3b4e0af13e","ecc9b35bf13bd5459350da564646d05c5664a7476fe5acdf1305440f88ed784c","f4470c3fca4dbef1b2488d016fae25978effc586a1f83cb29ac8cb6ab5bc2d50","141319b1a84827e1046e93741bf8a9a15a916d49684ab04925ac4ce4573eea23","d54b606094287758dcf19064a8d91c727346aadaa9388732e73c4315b7c606f9","49030e42ce4152e715a7ddaa10e592f8e61d00f70ef11f48546711f159d985df","b96761b1e7ebd1e8464a78a98fe52f53ce6035c32b4b2b12307a629a551ff7cf","d4786e2581571c863c7d12231c3afb6d4cef390c0ac9a24b243293721d28ea95","ed28e3d3530544f1cf2b43d1956b7bd13b63c612d963a8fb37387aa1a5e11460","05b127365cf115d4978a7997ee98f9b48f0ddc552b981c18aa2ee1b3e6df42c6","9d11dd6843f298b01b34bd7f7e4b1037489871531d14b58199b7cba1ac0841e6","f79e90fa4091de4fc2ec70f5bf67b24393285c112658e0d810e6bd711387fbb9","99f1fc0f09230ce745b6a256ba7082e6e51a2907abda3d9e735a5c8188bb4ba1","477f86cce983b9c91a36fdcd4a7ce21144a08dee9b1aafb91b9c70e57f717ce6","b03d2e6bb4a7d71c66a66ff9e9c93549cae4b593f634a4ea2a1f79f94200f5b4","9ddc0f53a81e631dcf39d5155f41ec12ed551b731efc3224f410667ba07b37dc","cf087ff9ae7c9954ad8612d071e5cdf34a6024ee1ae477217639e63a802a53dd","b64f62b94babb82cc78d3d1308631ae221552bb595202fc1d267e1c29ce7ba60","a91e24875f8a534497459e5ccb872c4438be3130d8d74b7e1104c5f94cdcf8c2","4f49f3d029eeeb3fed14d59625acd088b6b34f3b41c527afa09d29e4a7725c32","179795fd7ac7e7efcba3c36d539a1e8659fb40d77d0a3fab2c25562d99793086","4ba37d0b40b879eceaaca2802a1635f2e6d86d5c31e3ff2d2fd13e68dd2a6d3d","6b7f5dfba9cd3108f1410b56f6a84188eee23ab48a3621b209a67eea64293394","870c540da9fafde331a3316cee50c17ad76ddb9160b78b317bef2e6f6fc4bac0","470b4cccaea895d8a5820aed088357e380d66b8e7510f0a1ea9b575850160241","8a55f8942af0aec1e0df3ab328b974a7888ffd60ded48cc6862013da0f41afbc","2e51e8409f28baf93e665df2a9d646a1bf9ac8703cbf9a6766cfdefa249d5780","99ef1a23e95910287d39493d8d9d7d1f0b498286f2b1fdbc0b01495f10cf0958","6652200c53a4551efe2a7541072d817562812003f9d9ef0ec17995aa232378f8","39c6c01194df72dda97da2072335c38231ced9b39afa280452afcca901e73643","12097e411d948f77b7b6fa4656c6573481c1b4e2864c1fca9d5b296096707c45","cbe53bf1976aee6cec830a848c6ac132def1503cffde82ccfe5bd15e75cbaa72","eeab5dcfff92dbabb7e285445aba47bd5135a4a3502df59ac546847aeb5a964f","5ea8279a578027abefab9c17cef186cccf000306685e5f2ee78bdf62cae568dd","0607767d89ad9c7686dbb01b37248290b2fa7364b2bf37d86afd51b88756fe66","e4fd5f45c08b52dae40f4cdff45e8681e76b5af5761356c4caed4ca750dc65cd","145b1c82caa2a6d703108444a5cf03e9cb8c3cd3f19299582a564276dbbba734","736b22ec91ae9b4b2b15e8d8c220f6c152d4f2228f6d46c16e6a9b98b4733120","ac776cb8b40f92cdd307b16b83e18eeb1fbaa5b5d6bd992b3fda0b4d6de8524c","65ba30e2202fdf6f37da0f7cfe31dfb5308c9209885aaf4cef4d572fd14e2903","54e8389455ec2252de063e83d3ce72529d674e6d2dc2070661f01d4f76b63475","fbbbfb525dd0255ee332d51f59648265aaa20c2e9eff007765cf4d4a6940a849","8de5e418f34d04f6ea947ce31852092a24a705862e6b810ca9f83c2d5f9cda4d","ea6040989964f012fd3a92a3170891f5f155430b8bbfa4976cde8d11513b62d9","14d94547b5deca767137fbd14dae73e888f3516c742fad18b83be333b38f0b88","47f05203f6368d56158cda2e79167777fc9dcb0c671ef3aabc205a1636c26a29"]; -contract("Market", async function([user1, user2, user3, user4, user5, user6, user7, user8, user9, user10]) { - it("1.Scenario 1 - Stake in ETH < minstake (no stake in LOT) and time passed < min time passed", async () => { - let tokenPrice = 0.01; - let masterInstance = await OwnedUpgradeabilityProxy.deployed(); - masterInstance = await Master.at(masterInstance.address); - let plotusToken = await PlotusToken.deployed(); - let BLOTInstance = await BLOT.deployed(); - let MockchainLinkInstance = await MockchainLinkBTC.deployed(); - let plotusNewAddress = await masterInstance.getLatestAddress(web3.utils.toHex("PL")); - tokenController =await TokenController.at(await masterInstance.getLatestAddress(web3.utils.toHex("TC"))); - let plotusNewInstance = await Plotus.at(plotusNewAddress); - let marketConfig = await plotusNewInstance.marketUtility(); - marketConfig = await MarketConfig.at(marketConfig); - const openMarkets = await plotusNewInstance.getOpenMarkets(); - //console.log("marketType", openMarkets["_marketTypes"][2] / 1); - marketInstance = await Market.at(openMarkets["_openMarkets"][2]); - await marketConfig.setMockPriceFlag(false); - await increaseTime(10001); - assert.ok(marketInstance); +truncNumber = (n) => Math.trunc(n * Math.pow(10, 2)) / Math.pow(10, 2); +let masterInstance,plotusToken,BLOTInstance,MockchainLinkInstance,allMarkets; - await MockchainLinkInstance.setLatestAnswer(1195000000000); - let currentPriceAfter = await MockchainLinkInstance.latestAnswer(); - //console.log(currentPriceAfter / 1); - - await marketInstance.setOptionRangesPublic(11900, 12000); - let priceOption1 = await marketInstance.getOptionPrice(1); - let priceOption2 = await marketInstance.getOptionPrice(2); - let priceOption3 = await marketInstance.getOptionPrice(3); - //console.log(priceOption1 / 1, priceOption2 / 1, priceOption3 / 1); - - await marketInstance.placePrediction("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", "1000000000000000000", 1, 1, { - value: "1000000000000000000", - from: user1, - }); - - await marketInstance.placePrediction("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", "2000000000000000000", 2, 1, { - value: "2000000000000000000", - from: user2, - }); - - await marketInstance.placePrediction("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", "10000000000000000000", 3, 1, { - value: "10000000000000000000", - from: user3, - }); - - await increaseTime(7200); - let currentPriceAfter_af = await MockchainLinkInstance.latestAnswer(); - //console.log(currentPriceAfter_af / 1); - let priceOption1_af = await marketInstance.getOptionPrice(1); - let priceOption2_af = await marketInstance.getOptionPrice(2); - let priceOption3_af = await marketInstance.getOptionPrice(3); - let optionPriceETH1 = priceOption1_af / 1; - let optionPriceLOT1 = priceOption1_af / tokenPrice; - //console.log("Round off ETH price of option1", optionPriceETH1 / 1000); - //console.log("Round off LOT price of option1", optionPriceLOT1 / 1000); - let optionPriceETH2 = priceOption2_af / 1; - let optionPriceLOT2 = priceOption2_af / 1 / tokenPrice; - //console.log("Round off ETH price of option2", optionPriceETH2 / 1000); - //console.log("Round off LOT price of option2", optionPriceLOT2 / 1000); - let optionPriceETH3 = priceOption3_af / 1; - let optionPriceLOT3 = priceOption3_af / 1 / tokenPrice; - //console.log("Round off ETH price of option3", optionPriceETH3 / 1000); - //console.log("Round off LOT price of option3", optionPriceLOT3 / 1000); - }); -}); +contract("Market", async function([user1, user2, user3, user4]) { -contract("Market", async function([user1, user2, user3, user4, user5, user6, user7, user8, user9, user10]) { - it("2.Scenario 2 - Stake in LOT< minstake (no stake in ETH) and time passed < min time passed", async () => { - let tokenPrice = 0.01; - let masterInstance = await OwnedUpgradeabilityProxy.deployed(); + before(async function () { + masterInstance = await OwnedUpgradeabilityProxy.deployed(); masterInstance = await Master.at(masterInstance.address); - let plotusToken = await PlotusToken.deployed(); - let BLOTInstance = await BLOT.deployed(); - let MockchainLinkInstance = await MockchainLinkBTC.deployed(); - let plotusNewAddress = await masterInstance.getLatestAddress(web3.utils.toHex("PL")); - tokenController =await TokenController.at(await masterInstance.getLatestAddress(web3.utils.toHex("TC"))); - let plotusNewInstance = await Plotus.at(plotusNewAddress); - let marketConfig = await plotusNewInstance.marketUtility(); - marketConfig = await MarketConfig.at(marketConfig); - const openMarkets = await plotusNewInstance.getOpenMarkets(); - //console.log("marketType", openMarkets["_marketTypes"][2] / 1); - marketInstance = await Market.at(openMarkets["_openMarkets"][2]); + plotusToken = await PlotusToken.deployed(); + BLOTInstance = await BLOT.deployed(); + MockchainLinkInstance = await MockchainLinkBTC.deployed(); + allMarkets = await AllMarkets.at(await masterInstance.getLatestAddress(web3.utils.toHex("AM"))); + marketConfig = await MarketConfig.at(await masterInstance.getLatestAddress(web3.utils.toHex("MU"))); + await marketConfig.setMockPriceFlag(false); - await increaseTime(10001); - assert.ok(marketInstance); + let expireT = await allMarkets.getMarketData(3); + + await increaseTimeTo(expireT[5]); await MockchainLinkInstance.setLatestAnswer(1195000000000); let currentPriceAfter = await MockchainLinkInstance.latestAnswer(); - //console.log(currentPriceAfter / 1); - await marketInstance.setOptionRangesPublic(11900, 12000); - let priceOption1 = await marketInstance.getOptionPrice(1); - let priceOption2 = await marketInstance.getOptionPrice(2); - let priceOption3 = await marketInstance.getOptionPrice(3); - //console.log(priceOption1 / 1, priceOption2 / 1, priceOption3 / 1); - - // await marketConfig.setAMLComplianceStatus(user1, true); - // await marketConfig.setAMLComplianceStatus(user2, true); - // await marketConfig.setAMLComplianceStatus(user3, true); - // await marketConfig.setAMLComplianceStatus(user4, true); - // await marketConfig.setAMLComplianceStatus(user5, true); - - // await marketConfig.setKYCComplianceStatus(user1, true); - // await marketConfig.setKYCComplianceStatus(user2, true); - // await marketConfig.setKYCComplianceStatus(user3, true); - // await marketConfig.setKYCComplianceStatus(user4, true); - // await marketConfig.setKYCComplianceStatus(user5, true); - - await plotusToken.approve(tokenController.address, "10000000000000000000000"); - await marketInstance.placePrediction(plotusToken.address, "100000000000000000000", 1, 1, { - from: user1, - }); - - await marketInstance.placePrediction(plotusToken.address, "100000000000000000000", 2, 1, { - from: user1, - }); - - await marketInstance.placePrediction(plotusToken.address, "100000000000000000000", 3, 1, { - from: user1, - }); - - await increaseTime(7200); - let currentPriceAfter_af = await MockchainLinkInstance.latestAnswer(); - //console.log(currentPriceAfter_af / 1); - let priceOption1_af = await marketInstance.getOptionPrice(1); - let priceOption2_af = await marketInstance.getOptionPrice(2); - let priceOption3_af = await marketInstance.getOptionPrice(3); - let optionPriceETH1 = priceOption1_af / 1; - let optionPriceLOT1 = priceOption1_af / tokenPrice; - //console.log("Round off ETH price of option1", optionPriceETH1 / 1000); - //console.log("Round off LOT price of option1", optionPriceLOT1 / 1000); - let optionPriceETH2 = priceOption2_af / 1; - let optionPriceLOT2 = priceOption2_af / 1 / tokenPrice; - //console.log("Round off ETH price of option2", optionPriceETH2 / 1000); - //console.log("Round off LOT price of option2", optionPriceLOT2 / 1000); - let optionPriceETH3 = priceOption3_af / 1; - let optionPriceLOT3 = priceOption3_af / 1 / tokenPrice; - //console.log("Round off ETH price of option3", optionPriceETH3 / 1000); - //console.log("Round off LOT price of option3", optionPriceLOT3 / 1000); + }); + + it("1.Scenario 1 - Stake < minstakes and time passed < min time passed", async () => { + + await allMarkets.createMarket(0, 1); + await increaseTime(2*3600); + + + await plotusToken.transfer(user2, toWei(10000)); + await plotusToken.approve(allMarkets.address, toWei(100000), { from: user2 }); + let functionSignature = encode3("depositAndPlacePrediction(uint,uint,address,uint64,uint256)", toWei(10000), 7, plotusToken.address, 10000*1e8, 1); + await signAndExecuteMetaTx( + privateKeyList[1], + user2, + functionSignature, + allMarkets, + "AM" + ); + + await plotusToken.transfer(user3, toWei(2000)); + await plotusToken.approve(allMarkets.address, toWei(100000), { from: user3 }); + functionSignature = encode3("depositAndPlacePrediction(uint,uint,address,uint64,uint256)", toWei(2000), 7, plotusToken.address, 2000*1e8, 2); + await signAndExecuteMetaTx( + privateKeyList[2], + user3, + functionSignature, + allMarkets, + "AM" + ); + + await plotusToken.transfer(user4, toWei(5000)); + await plotusToken.approve(allMarkets.address, toWei(100000), { from: user4 }); + functionSignature = encode3("depositAndPlacePrediction(uint,uint,address,uint64,uint256)", toWei(5000), 7, plotusToken.address, 5000*1e8, 3); + await signAndExecuteMetaTx( + privateKeyList[3], + user4, + functionSignature, + allMarkets, + "AM" + ); + assert.equal(await marketConfig.getOptionPrice(7,1), 25000); + assert.equal(await marketConfig.getOptionPrice(7,2), 50000); + assert.equal(await marketConfig.getOptionPrice(7,3), 25000); }); -}); -contract("Market", async function([user1, user2, user3, user4, user5, user6, user7, user8, user9, user10]) { - it("3.Scenario 3 - Stake in LOT+ETH> minstake and time passed < min time passed", async () => { - let tokenPrice = 0.01; - let masterInstance = await OwnedUpgradeabilityProxy.deployed(); - masterInstance = await Master.at(masterInstance.address); - let plotusToken = await PlotusToken.deployed(); - let BLOTInstance = await BLOT.deployed(); - let MockchainLinkInstance = await MockchainLinkBTC.deployed(); - let plotusNewAddress = await masterInstance.getLatestAddress(web3.utils.toHex("PL")); - tokenController =await TokenController.at(await masterInstance.getLatestAddress(web3.utils.toHex("TC"))); - let plotusNewInstance = await Plotus.at(plotusNewAddress); - let marketConfig = await plotusNewInstance.marketUtility(); - marketConfig = await MarketConfig.at(marketConfig); - const openMarkets = await plotusNewInstance.getOpenMarkets(); - //console.log("marketType", openMarkets["_marketTypes"][2] / 1); - marketInstance = await Market.at(openMarkets["_openMarkets"][2]); - await marketConfig.setMockPriceFlag(false); - await increaseTime(10001); - assert.ok(marketInstance); + it("2.Scenario 2 - Stake > minstakes and time passed < min time passed", async () => { + - await MockchainLinkInstance.setLatestAnswer(1195000000000); - let currentPriceAfter = await MockchainLinkInstance.latestAnswer(); - //console.log(currentPriceAfter / 1); - await marketInstance.setOptionRangesPublic(11900, 12000); - let priceOption1 = await marketInstance.getOptionPrice(1); - let priceOption2 = await marketInstance.getOptionPrice(2); - let priceOption3 = await marketInstance.getOptionPrice(3); - //console.log(priceOption1 / 1, priceOption2 / 1, priceOption3 / 1); - - // await marketConfig.setAMLComplianceStatus(user1, true); - // await marketConfig.setAMLComplianceStatus(user2, true); - // await marketConfig.setAMLComplianceStatus(user3, true); - // await marketConfig.setAMLComplianceStatus(user4, true); - // await marketConfig.setAMLComplianceStatus(user5, true); - - // await marketConfig.setKYCComplianceStatus(user1, true); - // await marketConfig.setKYCComplianceStatus(user2, true); - // await marketConfig.setKYCComplianceStatus(user3, true); - // await marketConfig.setKYCComplianceStatus(user4, true); - // await marketConfig.setKYCComplianceStatus(user5, true); - - await plotusToken.approve(tokenController.address, "10000000000000000000000"); - await marketInstance.placePrediction(plotusToken.address, "100000000000000000000", 1, 1, { - from: user1, - }); - - await marketInstance.placePrediction(plotusToken.address, "100000000000000000000", 2, 1, { - from: user1, - }); - - await marketInstance.placePrediction(plotusToken.address, "100000000000000000000", 3, 1, { - from: user1, - }); - - await marketInstance.placePrediction("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", "1000000000000000000", 1, 1, { - value: "1000000000000000000", - from: user1, - }); - - await marketInstance.placePrediction("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", "10000000000000000000", 2, 1, { - value: "10000000000000000000", - from: user2, - }); - - await marketInstance.placePrediction("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", "5000000000000000000", 3, 1, { - value: "5000000000000000000", - from: user2, - }); - - await increaseTime(7200); - let currentPriceAfter_af = await MockchainLinkInstance.latestAnswer(); - //console.log(currentPriceAfter_af / 1); - let priceOption1_af = await marketInstance.getOptionPrice(1); - let priceOption2_af = await marketInstance.getOptionPrice(2); - let priceOption3_af = await marketInstance.getOptionPrice(3); - let optionPriceETH1 = priceOption1_af / 1; - let optionPriceLOT1 = priceOption1_af / tokenPrice; - //console.log("Round off ETH price of option1", optionPriceETH1 / 1000); - //console.log("Round off LOT price of option1", optionPriceLOT1 / 1000); - let optionPriceETH2 = priceOption2_af / 1; - let optionPriceLOT2 = priceOption2_af / 1 / tokenPrice; - //console.log("Round off ETH price of option2", optionPriceETH2 / 1000); - //console.log("Round off LOT price of option2", optionPriceLOT2 / 1000); - let optionPriceETH3 = priceOption3_af / 1; - let optionPriceLOT3 = priceOption3_af / 1 / tokenPrice; - //console.log("Round off ETH price of option3", optionPriceETH3 / 1000); - //console.log("Round off LOT price of option3", optionPriceLOT3 / 1000); - }); -}); + let expireT = await allMarkets.getMarketData(7); -contract("Market", async function([user1, user2, user3, user4, user5, user6, user7, user8, user9, user10]) { - it("4.Scenario 3 - Stake in LOT+ETH> minstake and time passed < min time passed", async () => { - let tokenPrice = 0.01; - let masterInstance = await OwnedUpgradeabilityProxy.deployed(); - masterInstance = await Master.at(masterInstance.address); - let plotusToken = await PlotusToken.deployed(); - let BLOTInstance = await BLOT.deployed(); - let MockchainLinkInstance = await MockchainLinkBTC.deployed(); - let plotusNewAddress = await masterInstance.getLatestAddress(web3.utils.toHex("PL")); - tokenController =await TokenController.at(await masterInstance.getLatestAddress(web3.utils.toHex("TC"))); - let plotusNewInstance = await Plotus.at(plotusNewAddress); - let marketConfig = await plotusNewInstance.marketUtility(); - marketConfig = await MarketConfig.at(marketConfig); - const openMarkets = await plotusNewInstance.getOpenMarkets(); - //console.log("marketType", openMarkets["_marketTypes"][2] / 1); - marketInstance = await Market.at(openMarkets["_openMarkets"][2]); - await marketConfig.setMockPriceFlag(false); - await increaseTime(10001); - assert.ok(marketInstance); + await increaseTimeTo(expireT[5]); - await MockchainLinkInstance.setLatestAnswer(1195000000000); - let currentPriceAfter = await MockchainLinkInstance.latestAnswer(); - //console.log(currentPriceAfter / 1); - await marketInstance.setOptionRangesPublic(11900, 12000); - let priceOption1 = await marketInstance.getOptionPrice(1); - let priceOption2 = await marketInstance.getOptionPrice(2); - let priceOption3 = await marketInstance.getOptionPrice(3); - //console.log(priceOption1 / 1, priceOption2 / 1, priceOption3 / 1); - - // await marketConfig.setAMLComplianceStatus(user1, true); - // await marketConfig.setAMLComplianceStatus(user2, true); - // await marketConfig.setAMLComplianceStatus(user3, true); - // await marketConfig.setAMLComplianceStatus(user4, true); - // await marketConfig.setAMLComplianceStatus(user5, true); - - // await marketConfig.setKYCComplianceStatus(user1, true); - // await marketConfig.setKYCComplianceStatus(user2, true); - // await marketConfig.setKYCComplianceStatus(user3, true); - // await marketConfig.setKYCComplianceStatus(user4, true); - // await marketConfig.setKYCComplianceStatus(user5, true); - - await plotusToken.approve(tokenController.address, "10000000000000000000000"); - await marketInstance.placePrediction(plotusToken.address, "100000000000000000000", 1, 1, { - from: user1, - }); - - await marketInstance.placePrediction(plotusToken.address, "100000000000000000000", 2, 1, { - from: user1, - }); - - await marketInstance.placePrediction(plotusToken.address, "100000000000000000000", 3, 1, { - from: user1, - }); - - await marketInstance.placePrediction("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", "1000000000000000000", 1, 1, { - value: "1000000000000000000", - from: user1, - }); - - await marketInstance.placePrediction("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", "10000000000000000000", 2, 1, { - value: "10000000000000000000", - from: user2, - }); - - await marketInstance.placePrediction("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", "5000000000000000000", 3, 1, { - value: "5000000000000000000", - from: user2, - }); - - await increaseTime(7200); - let currentPriceAfter_af = await MockchainLinkInstance.latestAnswer(); - //console.log(currentPriceAfter_af / 1); - let priceOption1_af = await marketInstance.getOptionPrice(1); - let priceOption2_af = await marketInstance.getOptionPrice(2); - let priceOption3_af = await marketInstance.getOptionPrice(3); - let optionPriceETH1 = priceOption1_af / 1; - let optionPriceLOT1 = priceOption1_af / tokenPrice; - //console.log("Round off ETH price of option1", optionPriceETH1 / 1000); - //console.log("Round off LOT price of option1", optionPriceLOT1 / 1000); - let optionPriceETH2 = priceOption2_af / 1; - let optionPriceLOT2 = priceOption2_af / 1 / tokenPrice; - //console.log("Round off ETH price of option2", optionPriceETH2 / 1000); - //console.log("Round off LOT price of option2", optionPriceLOT2 / 1000); - let optionPriceETH3 = priceOption3_af / 1; - let optionPriceLOT3 = priceOption3_af / 1 / tokenPrice; - //console.log("Round off ETH price of option3", optionPriceETH3 / 1000); - //console.log("Round off LOT price of option3", optionPriceLOT3 / 1000); - }); -}); -contract("Market", async function([user1, user2, user3, user4, user5, user6, user7, user8, user9, user10]) { - it("5.Scenario 4 - Stake in LOT+ETH> minstake and time passed > min time passed", async () => { - let tokenPrice = 0.01; - let masterInstance = await OwnedUpgradeabilityProxy.deployed(); - masterInstance = await Master.at(masterInstance.address); - let plotusToken = await PlotusToken.deployed(); - let BLOTInstance = await BLOT.deployed(); - let MockchainLinkInstance = await MockchainLinkBTC.deployed(); - let plotusNewAddress = await masterInstance.getLatestAddress(web3.utils.toHex("PL")); - tokenController =await TokenController.at(await masterInstance.getLatestAddress(web3.utils.toHex("TC"))); - let plotusNewInstance = await Plotus.at(plotusNewAddress); - let marketConfig = await plotusNewInstance.marketUtility(); - marketConfig = await MarketConfig.at(marketConfig); - const openMarkets = await plotusNewInstance.getOpenMarkets(); - //console.log("marketType", openMarkets["_marketTypes"][2] / 1); - marketInstance = await Market.at(openMarkets["_openMarkets"][2]); - await marketConfig.setMockPriceFlag(false); - await increaseTime(10001); - assert.ok(marketInstance); + await allMarkets.createMarket(0, 1); - await MockchainLinkInstance.setLatestAnswer(1195000000000); - let currentPriceAfter = await MockchainLinkInstance.latestAnswer(); - //console.log(currentPriceAfter / 1); - await marketInstance.setOptionRangesPublic(11900, 12000); - let priceOption1 = await marketInstance.getOptionPrice(1); - let priceOption2 = await marketInstance.getOptionPrice(2); - let priceOption3 = await marketInstance.getOptionPrice(3); - //console.log(priceOption1 / 1, priceOption2 / 1, priceOption3 / 1); - - // await marketConfig.setAMLComplianceStatus(user1, true); - // await marketConfig.setAMLComplianceStatus(user2, true); - // await marketConfig.setAMLComplianceStatus(user3, true); - // await marketConfig.setAMLComplianceStatus(user4, true); - // await marketConfig.setAMLComplianceStatus(user5, true); - - // await marketConfig.setKYCComplianceStatus(user1, true); - // await marketConfig.setKYCComplianceStatus(user2, true); - // await marketConfig.setKYCComplianceStatus(user3, true); - // await marketConfig.setKYCComplianceStatus(user4, true); - // await marketConfig.setKYCComplianceStatus(user5, true); - - await plotusToken.approve(tokenController.address, "10000000000000000000000"); - await marketInstance.placePrediction(plotusToken.address, "1000000000000000000000", 1, 1, { - from: user1, - }); - - await marketInstance.placePrediction(plotusToken.address, "100000000000000000000", 2, 1, { - from: user1, - }); - - await marketInstance.placePrediction(plotusToken.address, "100000000000000000000", 3, 1, { - from: user1, - }); - - await marketInstance.placePrediction("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", "1000000000000000000", 1, 1, { - value: "1000000000000000000", - from: user1, - }); - - await marketInstance.placePrediction("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", "10000000000000000000", 2, 1, { - value: "10000000000000000000", - from: user2, - }); - - await marketInstance.placePrediction("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", "5000000000000000000", 3, 1, { - value: "5000000000000000000", - from: user2, - }); - - await increaseTime(25200); - let currentPriceAfter_af = await MockchainLinkInstance.latestAnswer(); - //console.log(currentPriceAfter_af / 1); - let priceOption1_af = await marketInstance.getOptionPrice(1); - let priceOption2_af = await marketInstance.getOptionPrice(2); - let priceOption3_af = await marketInstance.getOptionPrice(3); - let optionPriceETH1 = priceOption1_af / 1; - let optionPriceLOT1 = priceOption1_af / tokenPrice; - //console.log("Round off ETH price of option1", optionPriceETH1 / 1000); - //console.log("Round off LOT price of option1", optionPriceLOT1 / 1000); - let optionPriceETH2 = priceOption2_af / 1; - let optionPriceLOT2 = priceOption2_af / 1 / tokenPrice; - //console.log("Round off ETH price of option2", optionPriceETH2 / 1000); - //console.log("Round off LOT price of option2", optionPriceLOT2 / 1000); - let optionPriceETH3 = priceOption3_af / 1; - let optionPriceLOT3 = priceOption3_af / 1 / tokenPrice; - //console.log("Round off ETH price of option3", optionPriceETH3 / 1000); - //console.log("Round off LOT price of option3", optionPriceLOT3 / 1000); + + + await plotusToken.transfer(user2, toWei(10000)); + await plotusToken.approve(allMarkets.address, toWei(100000), { from: user2 }); + let functionSignature = encode3("depositAndPlacePrediction(uint,uint,address,uint64,uint256)", toWei(10000), 8, plotusToken.address, 10000*1e8, 1); + await signAndExecuteMetaTx( + privateKeyList[1], + user2, + functionSignature, + allMarkets, + "AM" + ); + + await plotusToken.transfer(user3, toWei(5000)); + await plotusToken.approve(allMarkets.address, toWei(100000), { from: user3 }); + functionSignature = encode3("depositAndPlacePrediction(uint,uint,address,uint64,uint256)", toWei(5000), 8, plotusToken.address, 5000*1e8, 2); + await signAndExecuteMetaTx( + privateKeyList[2], + user3, + functionSignature, + allMarkets, + "AM" + ); + + await plotusToken.transfer(user4, toWei(40000)); + await plotusToken.approve(allMarkets.address, toWei(100000), { from: user4 }); + functionSignature = encode3("depositAndPlacePrediction(uint,uint,address,uint64,uint256)", toWei(40000), 8, plotusToken.address, 40000*1e8, 3); + await signAndExecuteMetaTx( + privateKeyList[3], + user4, + functionSignature, + allMarkets, + "AM" + ); + + let optionPricePaams = await allMarkets.getMarketOptionPricingParams(8,1); + await increaseTimeTo(optionPricePaams[1]/1+2*3600); + + + assert.equal(truncNumber((await marketConfig.getOptionPrice(8,1))/1e5), 0.19); + assert.equal(truncNumber((await marketConfig.getOptionPrice(8,2))/1e5), 0.16); + assert.equal(truncNumber((await marketConfig.getOptionPrice(8,3))/1e5), 0.63); }); -}); -contract("Market", async function([user1, user2, user3, user4, user5, user6, user7, user8, user9, user10]) { - it("6.Scenario 5 - Stake in LOT+ETH> minstake and time passed > min time passed, max distance = 2", async () => { - let tokenPrice = 0.01; - let masterInstance = await OwnedUpgradeabilityProxy.deployed(); - masterInstance = await Master.at(masterInstance.address); - let plotusToken = await PlotusToken.deployed(); - let BLOTInstance = await BLOT.deployed(); - let MockchainLinkInstance = await MockchainLinkBTC.deployed(); - let plotusNewAddress = await masterInstance.getLatestAddress(web3.utils.toHex("PL")); - tokenController =await TokenController.at(await masterInstance.getLatestAddress(web3.utils.toHex("TC"))); - let plotusNewInstance = await Plotus.at(plotusNewAddress); - let marketConfig = await plotusNewInstance.marketUtility(); - marketConfig = await MarketConfig.at(marketConfig); - const openMarkets = await plotusNewInstance.getOpenMarkets(); - //console.log("marketType", openMarkets["_marketTypes"][2] / 1); - marketInstance = await Market.at(openMarkets["_openMarkets"][2]); - await marketConfig.setMockPriceFlag(false); - await increaseTime(10001); - assert.ok(marketInstance); + it("3.Scenario 3 - Stake > minstakes and time passed > min time passed", async () => { + + let expireT = await allMarkets.getMarketData(8); + + await increaseTimeTo(expireT[5]); + + await allMarkets.createMarket(0, 1); + + + await plotusToken.transfer(user2, toWei(10000)); + await plotusToken.approve(allMarkets.address, toWei(100000), { from: user2 }); + let functionSignature = encode3("depositAndPlacePrediction(uint,uint,address,uint64,uint256)", toWei(10000), 9, plotusToken.address, 10000*1e8, 1); + await signAndExecuteMetaTx( + privateKeyList[1], + user2, + functionSignature, + allMarkets, + "AM" + ); + + await plotusToken.transfer(user3, toWei(5000)); + await plotusToken.approve(allMarkets.address, toWei(100000), { from: user3 }); + functionSignature = encode3("depositAndPlacePrediction(uint,uint,address,uint64,uint256)", toWei(5000), 9, plotusToken.address, 5000*1e8, 2); + await signAndExecuteMetaTx( + privateKeyList[2], + user3, + functionSignature, + allMarkets, + "AM" + ); + + await plotusToken.transfer(user4, toWei(40000)); + await plotusToken.approve(allMarkets.address, toWei(100000), { from: user4 }); + functionSignature = encode3("depositAndPlacePrediction(uint,uint,address,uint64,uint256)", toWei(40000), 9, plotusToken.address, 40000*1e8, 3); + await signAndExecuteMetaTx( + privateKeyList[3], + user4, + functionSignature, + allMarkets, + "AM" + ); + + let optionPricePaams = await allMarkets.getMarketOptionPricingParams(9,1); + await increaseTimeTo(optionPricePaams[1]/1+7*3600); + + + assert.equal(truncNumber((await marketConfig.getOptionPrice(9,1))/1e5), 0.20); + assert.equal(truncNumber((await marketConfig.getOptionPrice(9,2))/1e5), 0.20); + assert.equal(truncNumber((await marketConfig.getOptionPrice(9,3))/1e5), 0.59); + }); + it("4.Scenario 4 - Stake > minstakes and time passed > min time passed max distance = 2", async () => { + let expireT = await allMarkets.getMarketData(9); + + await increaseTimeTo(expireT[5]); + + await allMarkets.createMarket(0, 1); + + await plotusToken.transfer(user2, toWei(10000)); + await plotusToken.approve(allMarkets.address, toWei(100000), { from: user2 }); + let functionSignature = encode3("depositAndPlacePrediction(uint,uint,address,uint64,uint256)", toWei(10000), 10, plotusToken.address, 10000*1e8, 1); + await signAndExecuteMetaTx( + privateKeyList[1], + user2, + functionSignature, + allMarkets, + "AM" + ); + + await plotusToken.transfer(user3, toWei(5000)); + await plotusToken.approve(allMarkets.address, toWei(100000), { from: user3 }); + functionSignature = encode3("depositAndPlacePrediction(uint,uint,address,uint64,uint256)", toWei(5000), 10, plotusToken.address, 5000*1e8, 2); + await signAndExecuteMetaTx( + privateKeyList[2], + user3, + functionSignature, + allMarkets, + "AM" + ); + + await plotusToken.transfer(user4, toWei(40000)); + await plotusToken.approve(allMarkets.address, toWei(100000), { from: user4 }); + functionSignature = encode3("depositAndPlacePrediction(uint,uint,address,uint64,uint256)", toWei(40000), 10, plotusToken.address, 40000*1e8, 3); + await signAndExecuteMetaTx( + privateKeyList[3], + user4, + functionSignature, + allMarkets, + "AM" + ); await MockchainLinkInstance.setLatestAnswer(1222000000000); - let currentPriceAfter = await MockchainLinkInstance.latestAnswer(); - //console.log(currentPriceAfter / 1); - await marketInstance.setOptionRangesPublic(11900, 12000); - let priceOption1 = await marketInstance.getOptionPrice(1); - let priceOption2 = await marketInstance.getOptionPrice(2); - let priceOption3 = await marketInstance.getOptionPrice(3); - //console.log(priceOption1 / 1, priceOption2 / 1, priceOption3 / 1); - - // await marketConfig.setAMLComplianceStatus(user1, true); - // await marketConfig.setAMLComplianceStatus(user2, true); - // await marketConfig.setAMLComplianceStatus(user3, true); - // await marketConfig.setAMLComplianceStatus(user4, true); - // await marketConfig.setAMLComplianceStatus(user5, true); - - // await marketConfig.setKYCComplianceStatus(user1, true); - // await marketConfig.setKYCComplianceStatus(user2, true); - // await marketConfig.setKYCComplianceStatus(user3, true); - // await marketConfig.setKYCComplianceStatus(user4, true); - // await marketConfig.setKYCComplianceStatus(user5, true); - - await plotusToken.approve(tokenController.address, "10000000000000000000000"); - await marketInstance.placePrediction(plotusToken.address, "1000000000000000000000", 1, 1, { - from: user1, - }); - - await marketInstance.placePrediction(plotusToken.address, "100000000000000000000", 2, 1, { - from: user1, - }); - - await marketInstance.placePrediction(plotusToken.address, "100000000000000000000", 3, 1, { - from: user1, - }); - - await marketInstance.placePrediction("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", "1000000000000000000", 1, 1, { - value: "1000000000000000000", - from: user1, - }); - - await marketInstance.placePrediction("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", "10000000000000000000", 2, 1, { - value: "10000000000000000000", - from: user2, - }); - - await marketInstance.placePrediction("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", "5000000000000000000", 3, 1, { - value: "5000000000000000000", - from: user2, - }); - - await increaseTime(25200); - let currentPriceAfter_af = await MockchainLinkInstance.latestAnswer(); - //console.log(currentPriceAfter_af / 1); - let priceOption1_af = await marketInstance.getOptionPrice(1); - let priceOption2_af = await marketInstance.getOptionPrice(2); - let priceOption3_af = await marketInstance.getOptionPrice(3); - let optionPriceETH1 = priceOption1_af / 1; - let optionPriceLOT1 = priceOption1_af / tokenPrice; - //console.log("Round off ETH price of option1", optionPriceETH1 / 1000); - //console.log("Round off LOT price of option1", optionPriceLOT1 / 1000); - let optionPriceETH2 = priceOption2_af / 1; - let optionPriceLOT2 = priceOption2_af / 1 / tokenPrice; - //console.log("Round off ETH price of option2", optionPriceETH2 / 1000); - //console.log("Round off LOT price of option2", optionPriceLOT2 / 1000); - let optionPriceETH3 = priceOption3_af / 1; - let optionPriceLOT3 = priceOption3_af / 1 / tokenPrice; - //console.log("Round off ETH price of option3", optionPriceETH3 / 1000); - //console.log("Round off LOT price of option3", optionPriceLOT3 / 1000); + let optionPricePaams = await allMarkets.getMarketOptionPricingParams(10,1); + await increaseTimeTo(optionPricePaams[1]/1+7*3600); + assert.equal(truncNumber((await marketConfig.getOptionPrice(10,1))/1e5), 0.17); + assert.equal(truncNumber((await marketConfig.getOptionPrice(10,2))/1e5), 0.15); + assert.equal(truncNumber((await marketConfig.getOptionPrice(10,3))/1e5), 0.66); }); + }); diff --git a/test/04_dailyMarketOptionPriceManualFeed.js b/test/04_dailyMarketOptionPriceManualFeed.js new file mode 100644 index 000000000..4c74afb7e --- /dev/null +++ b/test/04_dailyMarketOptionPriceManualFeed.js @@ -0,0 +1,256 @@ +const { assert } = require("chai"); +const OwnedUpgradeabilityProxy = artifacts.require("OwnedUpgradeabilityProxy"); +const Master = artifacts.require("Master"); +const TokenController = artifacts.require("TokenController"); +const PlotusToken = artifacts.require("MockPLOT"); +const MarketConfig = artifacts.require("MockConfig"); +const BLOT = artifacts.require("BLOT"); +const Governance = artifacts.require("Governance"); +const MemberRoles = artifacts.require("MemberRoles"); +const ProposalCategory = artifacts.require("ProposalCategory"); +const AllMarkets = artifacts.require("AllMarkets"); +const increaseTime = require("./utils/increaseTime.js").increaseTime; +const increaseTimeTo = require("./utils/increaseTime.js").increaseTimeTo; +const { encode, encode1,encode3 } = require("./utils/encoder.js"); +const signAndExecuteMetaTx = require("./utils/signAndExecuteMetaTx.js").signAndExecuteMetaTx; +const { toHex, toWei, toChecksumAddress } = require("./utils/ethTools"); +const latestTime = require("./utils/latestTime.js").latestTime; +let privateKeyList = ["fb437e3e01939d9d4fef43138249f23dc1d0852e69b0b5d1647c087f869fabbd","7c85a1f1da3120c941b83d71a154199ee763307683f206b98ad92c3b4e0af13e","ecc9b35bf13bd5459350da564646d05c5664a7476fe5acdf1305440f88ed784c","f4470c3fca4dbef1b2488d016fae25978effc586a1f83cb29ac8cb6ab5bc2d50","141319b1a84827e1046e93741bf8a9a15a916d49684ab04925ac4ce4573eea23","d54b606094287758dcf19064a8d91c727346aadaa9388732e73c4315b7c606f9","49030e42ce4152e715a7ddaa10e592f8e61d00f70ef11f48546711f159d985df","b96761b1e7ebd1e8464a78a98fe52f53ce6035c32b4b2b12307a629a551ff7cf","d4786e2581571c863c7d12231c3afb6d4cef390c0ac9a24b243293721d28ea95","ed28e3d3530544f1cf2b43d1956b7bd13b63c612d963a8fb37387aa1a5e11460","05b127365cf115d4978a7997ee98f9b48f0ddc552b981c18aa2ee1b3e6df42c6","9d11dd6843f298b01b34bd7f7e4b1037489871531d14b58199b7cba1ac0841e6","f79e90fa4091de4fc2ec70f5bf67b24393285c112658e0d810e6bd711387fbb9","99f1fc0f09230ce745b6a256ba7082e6e51a2907abda3d9e735a5c8188bb4ba1","477f86cce983b9c91a36fdcd4a7ce21144a08dee9b1aafb91b9c70e57f717ce6","b03d2e6bb4a7d71c66a66ff9e9c93549cae4b593f634a4ea2a1f79f94200f5b4","9ddc0f53a81e631dcf39d5155f41ec12ed551b731efc3224f410667ba07b37dc","cf087ff9ae7c9954ad8612d071e5cdf34a6024ee1ae477217639e63a802a53dd","b64f62b94babb82cc78d3d1308631ae221552bb595202fc1d267e1c29ce7ba60","a91e24875f8a534497459e5ccb872c4438be3130d8d74b7e1104c5f94cdcf8c2","4f49f3d029eeeb3fed14d59625acd088b6b34f3b41c527afa09d29e4a7725c32","179795fd7ac7e7efcba3c36d539a1e8659fb40d77d0a3fab2c25562d99793086","4ba37d0b40b879eceaaca2802a1635f2e6d86d5c31e3ff2d2fd13e68dd2a6d3d","6b7f5dfba9cd3108f1410b56f6a84188eee23ab48a3621b209a67eea64293394","870c540da9fafde331a3316cee50c17ad76ddb9160b78b317bef2e6f6fc4bac0","470b4cccaea895d8a5820aed088357e380d66b8e7510f0a1ea9b575850160241","8a55f8942af0aec1e0df3ab328b974a7888ffd60ded48cc6862013da0f41afbc","2e51e8409f28baf93e665df2a9d646a1bf9ac8703cbf9a6766cfdefa249d5780","99ef1a23e95910287d39493d8d9d7d1f0b498286f2b1fdbc0b01495f10cf0958","6652200c53a4551efe2a7541072d817562812003f9d9ef0ec17995aa232378f8","39c6c01194df72dda97da2072335c38231ced9b39afa280452afcca901e73643","12097e411d948f77b7b6fa4656c6573481c1b4e2864c1fca9d5b296096707c45","cbe53bf1976aee6cec830a848c6ac132def1503cffde82ccfe5bd15e75cbaa72","eeab5dcfff92dbabb7e285445aba47bd5135a4a3502df59ac546847aeb5a964f","5ea8279a578027abefab9c17cef186cccf000306685e5f2ee78bdf62cae568dd","0607767d89ad9c7686dbb01b37248290b2fa7364b2bf37d86afd51b88756fe66","e4fd5f45c08b52dae40f4cdff45e8681e76b5af5761356c4caed4ca750dc65cd","145b1c82caa2a6d703108444a5cf03e9cb8c3cd3f19299582a564276dbbba734","736b22ec91ae9b4b2b15e8d8c220f6c152d4f2228f6d46c16e6a9b98b4733120","ac776cb8b40f92cdd307b16b83e18eeb1fbaa5b5d6bd992b3fda0b4d6de8524c","65ba30e2202fdf6f37da0f7cfe31dfb5308c9209885aaf4cef4d572fd14e2903","54e8389455ec2252de063e83d3ce72529d674e6d2dc2070661f01d4f76b63475","fbbbfb525dd0255ee332d51f59648265aaa20c2e9eff007765cf4d4a6940a849","8de5e418f34d04f6ea947ce31852092a24a705862e6b810ca9f83c2d5f9cda4d","ea6040989964f012fd3a92a3170891f5f155430b8bbfa4976cde8d11513b62d9","14d94547b5deca767137fbd14dae73e888f3516c742fad18b83be333b38f0b88","47f05203f6368d56158cda2e79167777fc9dcb0c671ef3aabc205a1636c26a29"]; +let nullAddress = "0x0000000000000000000000000000000000000000"; +truncNumber = (n) => Math.trunc(n * Math.pow(10, 2)) / Math.pow(10, 2); +let masterInstance,plotusToken,BLOTInstance,allMarkets,gv,mr,pc; + +contract("Market", async function([user1, user2, user3, user4]) { + + before(async function () { + masterInstance = await OwnedUpgradeabilityProxy.deployed(); + masterInstance = await Master.at(masterInstance.address); + plotusToken = await PlotusToken.deployed(); + BLOTInstance = await BLOT.deployed(); + allMarkets = await AllMarkets.at(await masterInstance.getLatestAddress(web3.utils.toHex("AM"))); + marketConfig = await MarketConfig.at(await masterInstance.getLatestAddress(web3.utils.toHex("MU"))); + let address = await masterInstance.getLatestAddress(toHex("GV")); + gv = await Governance.at(address); + address = await masterInstance.getLatestAddress(toHex("PC")); + pc = await ProposalCategory.at(address); + address = await masterInstance.getLatestAddress(toHex("MR")); + mr = await MemberRoles.at(address); + + await marketConfig.setMockPriceFlag(false); + let expireT = await allMarkets.getMarketData(3); + + await increaseTimeTo(expireT[5]); + + let pId = (await gv.getProposalLength()).toNumber(); + await gv.createProposal("Proposal2", "Proposal2", "Proposal2", 0); //Pid 3 + await gv.categorizeProposal(pId, 15, 0); + let startTime = (await latestTime()) / 1 + 2 * 604800; + let actionHash = encode("addMarketCurrency(bytes32,address,uint8,uint8,uint32)", toHex("ETH/PLOT"), nullAddress, 8, 1, startTime); + await gv.submitProposalWithSolution(pId, "addNewMarketCurrency", actionHash); + await gv.submitVote(pId, 1, { from: user1 }); + await increaseTime(604810); + await gv.closeProposal(pId); + let actionStatus = await gv.proposalActionStatus(pId); + assert.equal(actionStatus / 1, 3); + await increaseTime(604810); + + await marketConfig.setFeedPriceForMarketType(toHex("ETH/PLOT"),1195000000000); + + }); + + it("1.Scenario 1 - Stake < minstakes and time passed < min time passed", async () => { + + await allMarkets.createMarket(2, 1); + await increaseTime(2*3600); + + + await plotusToken.transfer(user2, toWei(10000)); + await plotusToken.approve(allMarkets.address, toWei(100000), { from: user2 }); + let functionSignature = encode3("depositAndPlacePrediction(uint,uint,address,uint64,uint256)", toWei(10000), 7, plotusToken.address, 10000*1e8, 1); + await signAndExecuteMetaTx( + privateKeyList[1], + user2, + functionSignature, + allMarkets, + "AM" + ); + + await plotusToken.transfer(user3, toWei(2000)); + await plotusToken.approve(allMarkets.address, toWei(100000), { from: user3 }); + functionSignature = encode3("depositAndPlacePrediction(uint,uint,address,uint64,uint256)", toWei(2000), 7, plotusToken.address, 2000*1e8, 2); + await signAndExecuteMetaTx( + privateKeyList[2], + user3, + functionSignature, + allMarkets, + "AM" + ); + + await plotusToken.transfer(user4, toWei(5000)); + await plotusToken.approve(allMarkets.address, toWei(100000), { from: user4 }); + functionSignature = encode3("depositAndPlacePrediction(uint,uint,address,uint64,uint256)", toWei(5000), 7, plotusToken.address, 5000*1e8, 3); + await signAndExecuteMetaTx( + privateKeyList[3], + user4, + functionSignature, + allMarkets, + "AM" + ); + assert.equal(await marketConfig.getOptionPrice(7,1), 25000); + assert.equal(await marketConfig.getOptionPrice(7,2), 50000); + assert.equal(await marketConfig.getOptionPrice(7,3), 25000); + }); + + it("2.Scenario 2 - Stake > minstakes and time passed < min time passed", async () => { + + + let expireT = await allMarkets.getMarketData(7); + + await increaseTimeTo(expireT[5]); + + + await allMarkets.createMarket(2, 1); + + + + await plotusToken.transfer(user2, toWei(10000)); + await plotusToken.approve(allMarkets.address, toWei(100000), { from: user2 }); + let functionSignature = encode3("depositAndPlacePrediction(uint,uint,address,uint64,uint256)", toWei(10000), 8, plotusToken.address, 10000*1e8, 1); + await signAndExecuteMetaTx( + privateKeyList[1], + user2, + functionSignature, + allMarkets, + "AM" + ); + + await plotusToken.transfer(user3, toWei(5000)); + await plotusToken.approve(allMarkets.address, toWei(100000), { from: user3 }); + functionSignature = encode3("depositAndPlacePrediction(uint,uint,address,uint64,uint256)", toWei(5000), 8, plotusToken.address, 5000*1e8, 2); + await signAndExecuteMetaTx( + privateKeyList[2], + user3, + functionSignature, + allMarkets, + "AM" + ); + + await plotusToken.transfer(user4, toWei(40000)); + await plotusToken.approve(allMarkets.address, toWei(100000), { from: user4 }); + functionSignature = encode3("depositAndPlacePrediction(uint,uint,address,uint64,uint256)", toWei(40000), 8, plotusToken.address, 40000*1e8, 3); + await signAndExecuteMetaTx( + privateKeyList[3], + user4, + functionSignature, + allMarkets, + "AM" + ); + + let optionPricePaams = await allMarkets.getMarketOptionPricingParams(8,1); + await increaseTimeTo(optionPricePaams[1]/1+2*3600); + + + assert.equal(truncNumber((await marketConfig.getOptionPrice(8,1))/1e5), 0.19); + assert.equal(truncNumber((await marketConfig.getOptionPrice(8,2))/1e5), 0.16); + assert.equal(truncNumber((await marketConfig.getOptionPrice(8,3))/1e5), 0.63); + }); + + it("3.Scenario 3 - Stake > minstakes and time passed > min time passed", async () => { + + let expireT = await allMarkets.getMarketData(8); + + await increaseTimeTo(expireT[5]); + + await allMarkets.createMarket(2, 1); + + + await plotusToken.transfer(user2, toWei(10000)); + await plotusToken.approve(allMarkets.address, toWei(100000), { from: user2 }); + let functionSignature = encode3("depositAndPlacePrediction(uint,uint,address,uint64,uint256)", toWei(10000), 9, plotusToken.address, 10000*1e8, 1); + await signAndExecuteMetaTx( + privateKeyList[1], + user2, + functionSignature, + allMarkets, + "AM" + ); + + await plotusToken.transfer(user3, toWei(5000)); + await plotusToken.approve(allMarkets.address, toWei(100000), { from: user3 }); + functionSignature = encode3("depositAndPlacePrediction(uint,uint,address,uint64,uint256)", toWei(5000), 9, plotusToken.address, 5000*1e8, 2); + await signAndExecuteMetaTx( + privateKeyList[2], + user3, + functionSignature, + allMarkets, + "AM" + ); + + await plotusToken.transfer(user4, toWei(40000)); + await plotusToken.approve(allMarkets.address, toWei(100000), { from: user4 }); + functionSignature = encode3("depositAndPlacePrediction(uint,uint,address,uint64,uint256)", toWei(40000), 9, plotusToken.address, 40000*1e8, 3); + await signAndExecuteMetaTx( + privateKeyList[3], + user4, + functionSignature, + allMarkets, + "AM" + ); + + let optionPricePaams = await allMarkets.getMarketOptionPricingParams(9,1); + await increaseTimeTo(optionPricePaams[1]/1+7*3600); + + + assert.equal(truncNumber((await marketConfig.getOptionPrice(9,1))/1e5), 0.20); + assert.equal(truncNumber((await marketConfig.getOptionPrice(9,2))/1e5), 0.20); + assert.equal(truncNumber((await marketConfig.getOptionPrice(9,3))/1e5), 0.59); + }); + + it("4.Scenario 4 - Stake > minstakes and time passed > min time passed max distance = 2", async () => { + let expireT = await allMarkets.getMarketData(9); + + await increaseTimeTo(expireT[5]); + + await allMarkets.createMarket(2, 1); + + await plotusToken.transfer(user2, toWei(10000)); + await plotusToken.approve(allMarkets.address, toWei(100000), { from: user2 }); + let functionSignature = encode3("depositAndPlacePrediction(uint,uint,address,uint64,uint256)", toWei(10000), 10, plotusToken.address, 10000*1e8, 1); + await signAndExecuteMetaTx( + privateKeyList[1], + user2, + functionSignature, + allMarkets, + "AM" + ); + + await plotusToken.transfer(user3, toWei(5000)); + await plotusToken.approve(allMarkets.address, toWei(100000), { from: user3 }); + functionSignature = encode3("depositAndPlacePrediction(uint,uint,address,uint64,uint256)", toWei(5000), 10, plotusToken.address, 5000*1e8, 2); + await signAndExecuteMetaTx( + privateKeyList[2], + user3, + functionSignature, + allMarkets, + "AM" + ); + + await plotusToken.transfer(user4, toWei(40000)); + await plotusToken.approve(allMarkets.address, toWei(100000), { from: user4 }); + functionSignature = encode3("depositAndPlacePrediction(uint,uint,address,uint64,uint256)", toWei(40000), 10, plotusToken.address, 40000*1e8, 3); + await signAndExecuteMetaTx( + privateKeyList[3], + user4, + functionSignature, + allMarkets, + "AM" + ); + await marketConfig.setFeedPriceForMarketType(toHex("ETH/PLOT"),1222000000000); + let optionPricePaams = await allMarkets.getMarketOptionPricingParams(10,1); + await increaseTimeTo(optionPricePaams[1]/1+7*3600); + assert.equal(truncNumber((await marketConfig.getOptionPrice(10,1))/1e5), 0.17); + assert.equal(truncNumber((await marketConfig.getOptionPrice(10,2))/1e5), 0.15); + assert.equal(truncNumber((await marketConfig.getOptionPrice(10,3))/1e5), 0.66); + }); + +}); diff --git a/test/05_disputeResolution.js b/test/05_disputeResolution.js deleted file mode 100644 index c8ac4b8ba..000000000 --- a/test/05_disputeResolution.js +++ /dev/null @@ -1,424 +0,0 @@ -const { assert } = require("chai"); -const OwnedUpgradeabilityProxy = artifacts.require('OwnedUpgradeabilityProxy'); -const Market = artifacts.require("MockMarket"); -const Plotus = artifacts.require("MarketRegistry"); -const Master = artifacts.require("Master"); -const PlotusToken = artifacts.require("MockPLOT"); -const TokenController = artifacts.require("MockTokenController"); -const MockchainLinkBTC = artifacts.require("MockChainLinkAggregator"); -const Governance = artifacts.require("Governance"); -const MarketConfig = artifacts.require("MockConfig"); -const MockUniswapRouter = artifacts.require("MockUniswapRouter"); -const ProposalCategory = artifacts.require('ProposalCategory'); -const MemberRoles = artifacts.require('MockMemberRoles'); -const BLOT = artifacts.require("BLOT"); -const web3 = Market.web3; -const gvProposal = require("./utils/gvProposal.js").gvProposalWithIncentiveViaTokenHolder; -const increaseTime = require("./utils/increaseTime.js").increaseTime; -const latestTime = require("./utils/latestTime.js").latestTime; -const encode = require("./utils/encoder.js").encode; -const {toHex, toWei, toChecksumAddress} = require('./utils/ethTools'); -const { assertRevert } = require('./utils/assertRevert'); -let gv,masterInstance, tokenController, mr; -contract("Market", ([ab1, ab2, ab3, ab4, dr1, dr2, dr3, notMember]) => { - it("1.if DR panel accepts", async () => { - masterInstance = await OwnedUpgradeabilityProxy.deployed(); - masterInstance = await Master.at(masterInstance.address); - let tokenControllerAdd = await masterInstance.getLatestAddress(web3.utils.toHex("TC")); - tokenController = await TokenController.at(tokenControllerAdd); - let plotusNewAddress = await masterInstance.getLatestAddress(web3.utils.toHex("PL")); - let plotusNewInstance = await Plotus.at(plotusNewAddress); - MockUniswapRouterInstance = await MockUniswapRouter.deployed(); - const openMarkets = await plotusNewInstance.getOpenMarkets(); - marketConfig = await plotusNewInstance.marketUtility(); - marketConfig = await MarketConfig.at(marketConfig); - marketInstance = await Market.at(openMarkets["_openMarkets"][0]); - await marketConfig.setOptionPrice(1, 9); - await marketConfig.setOptionPrice(2, 18); - await marketConfig.setOptionPrice(3, 27); - await increaseTime(10001); - assert.ok(marketInstance); - let nxmToken = await PlotusToken.deployed(); - let address = await masterInstance.getLatestAddress(web3.utils.toHex("GV")); - let plotusToken = await PlotusToken.deployed(); - gv = await Governance.at(address); - address = await masterInstance.getLatestAddress(web3.utils.toHex("PC")); - let pc = await ProposalCategory.at(address); - address = await masterInstance.getLatestAddress(web3.utils.toHex("MR")); - mr = await MemberRoles.at(address); - let tc = await TokenController.at(await masterInstance.getLatestAddress(web3.utils.toHex("MR"))); - await plotusToken.approve(mr.address, "10000000000000000000000"); - - await plotusToken.transfer(ab2, "50000000000000000000000"); - await plotusToken.transfer(ab3, "50000000000000000000000"); - await plotusToken.transfer(ab4, "50000000000000000000000"); - await plotusToken.transfer(dr1, "50000000000000000000000"); - await plotusToken.transfer(dr2, "50000000000000000000000"); - await plotusToken.transfer(dr3, "50000000000000000000000"); - await MockUniswapRouterInstance.setPrice("1000000000000000"); - await marketConfig.setPrice("1000000000000000"); - await plotusToken.approve(tokenController.address, "100000000000000000000"); - // Cannot raise dispute if there is no participation - await assertRevert(marketInstance.raiseDispute(1400000000000,"raise dispute","this is description","this is solution hash")); - await marketInstance.placePrediction(plotusToken.address, "100000000000000000000", 1, 1); - // cannot raise dispute if market is open - await plotusToken.approve(tokenController.address, "10000000000000000000000"); - await assertRevert(marketInstance.raiseDispute(1400000000000,"raise dispute","this is description","this is solution hash")); - - await increaseTime(3601); - // cannot raise dispute if market is closed but result is not out - await plotusToken.approve(tokenController.address, "10000000000000000000000"); - await assertRevert(marketInstance.raiseDispute(1400000000000,"raise dispute","this is description","this is solution hash")); - - await increaseTime(3600); - await marketInstance.calculatePredictionResult(100000000000); - // cannot raise dispute with less than minimum stake - await plotusToken.approve(tokenController.address, "10000000000000000000000"); - await assertRevert(marketInstance.raiseDispute(1400000000000,"raise dispute","this is description","this is solution hash",{from : notMember})); - //can raise dispute in cooling period and stake - await plotusToken.approve(tokenController.address, "10000000000000000000000"); - await marketInstance.raiseDispute(1400000000000,"raise dispute","this is description","this is solution hash"); - // cannot raise dispute multiple times - await assertRevert(marketInstance.raiseDispute(1400000000000,"raise dispute","this is description","this is solution hash")); - await assertRevert(marketInstance.resolveDispute(true, 100)); - let winningOption_af = await marketInstance.getMarketResults() - console.log("winningOption",winningOption_af[0]/1) - let proposalId = await gv.getProposalLength()-1; - console.log("proposalId",proposalId/1) - let userBalBefore = await plotusToken.balanceOf(ab1); - console.log("balance before accept proposal",userBalBefore/1) - - await plotusToken.approve(tokenController.address, "100000000000000000000000",{from : dr1}); - await tokenController.lock("0x4452","30000000000000000000000",(86400*20),{from : dr1}); - - await plotusToken.approve(tokenController.address, "100000000000000000000000",{from : dr2}); - await tokenController.lock("0x4452","30000000000000000000000",(86400*20),{from : dr2}); - - await assertRevert(gv.submitVote(proposalId, 1, {from:dr3})) //reverts as tokens not locked - - await plotusToken.approve(tokenController.address, "100000000000000000000000",{from : dr3}); - await tokenController.lock("0x4452","30000000000000000000000",(86400*20),{from : dr3}); - let roles = await mr.roles(dr3); - assert.equal(roles[0]/1, 2, "Not added to Token holder"); - assert.equal(roles[1]/1, 3, "Not added to DR"); - await gv.submitVote(proposalId, 1, {from:dr1}); - await gv.submitVote(proposalId, 1, {from:dr2}); - await gv.submitVote(proposalId, 1, {from:dr3}); - await increaseTime(604800); - await gv.closeProposal(proposalId); - // let data = await plotusNewInstance.marketDisputeData(marketInstance.address) - // assert.equal(data[0], proposalId,"dispute proposal mismatch"); - // let marketDetails = await plotusNewInstance.getMarketDetails(marketInstance.address); - // assert.equal(marketDetails[7]/1, 3, "status not updated"); - let proposalActionStatus = await gv.proposalActionStatus(proposalId); - assert.equal(proposalActionStatus/1, 3); - let userBalAfter = await plotusToken.balanceOf(ab1); - console.log("balance before accept proposal",userBalAfter/1) - let winningOption_afterVote = await marketInstance.getMarketResults() - assert.notEqual(winningOption_af[0]/1, winningOption_afterVote[0]/1); - console.log("winningOption After accept proposal",winningOption_afterVote[0]/1); - }); -}); -contract("Market", ([ab1, ab2, ab3, ab4, dr1, dr2, dr3, notMember]) => { - it("1.if quorum not reached proposal should be rejected", async () => { - masterInstance = await OwnedUpgradeabilityProxy.deployed(); - masterInstance = await Master.at(masterInstance.address); - let tokenControllerAdd = await masterInstance.getLatestAddress(web3.utils.toHex("TC")); - tokenController = await TokenController.at(tokenControllerAdd); - let plotusNewAddress = await masterInstance.getLatestAddress(web3.utils.toHex("PL")); - let plotusNewInstance = await Plotus.at(plotusNewAddress); - MockUniswapRouterInstance = await MockUniswapRouter.deployed(); - const openMarkets = await plotusNewInstance.getOpenMarkets(); - marketConfig = await plotusNewInstance.marketUtility(); - marketConfig = await MarketConfig.at(marketConfig); - marketInstance = await Market.at(openMarkets["_openMarkets"][0]); - await marketConfig.setOptionPrice(1, 9); - await marketConfig.setOptionPrice(2, 18); - await marketConfig.setOptionPrice(3, 27); - await increaseTime(10001); - assert.ok(marketInstance); - let nxmToken = await PlotusToken.deployed(); - let address = await masterInstance.getLatestAddress(web3.utils.toHex("GV")); - let plotusToken = await PlotusToken.deployed(); - gv = await Governance.at(address); - address = await masterInstance.getLatestAddress(web3.utils.toHex("PC")); - let pc = await ProposalCategory.at(address); - address = await masterInstance.getLatestAddress(web3.utils.toHex("MR")); - mr = await MemberRoles.at(address); - let tc = await TokenController.at(await masterInstance.getLatestAddress(web3.utils.toHex("MR"))); - await plotusToken.approve(mr.address, "10000000000000000000000"); - - await plotusToken.transfer(ab2, "50000000000000000000000"); - await plotusToken.transfer(ab3, "50000000000000000000000"); - await plotusToken.transfer(ab4, "50000000000000000000000"); - await plotusToken.transfer(dr1, "50000000000000000000000"); - await plotusToken.transfer(dr2, "50000000000000000000000"); - await plotusToken.transfer(dr3, "50000000000000000000000"); - await MockUniswapRouterInstance.setPrice("1000000000000000"); - await marketConfig.setPrice("1000000000000000"); - await plotusToken.approve(tokenController.address, "100000000000000000000"); - await marketInstance.placePrediction(plotusToken.address, "100000000000000000000", 1, 1); - // cannot raise dispute if market is open - await plotusToken.approve(tokenController.address, "10000000000000000000000"); - await assertRevert(marketInstance.raiseDispute(1400000000000,"raise dispute","this is description","this is solution hash")); - - await increaseTime(3601); - // cannot raise dispute if market is closed but result is not out - await plotusToken.approve(tokenController.address, "10000000000000000000000"); - await assertRevert(marketInstance.raiseDispute(1400000000000,"raise dispute","this is description","this is solution hash")); - - await increaseTime(3600); - await marketInstance.calculatePredictionResult(100000000000); - // cannot raise dispute with less than minimum stake - await plotusToken.approve(tokenController.address, "10000000000000000000000"); - await assertRevert(marketInstance.raiseDispute(1400000000000,"raise dispute","this is description","this is solution hash",{from : notMember})); - //can raise dispute in cooling period and stake - await plotusToken.approve(tokenController.address, "10000000000000000000000"); - await marketInstance.raiseDispute(1400000000000,"raise dispute","this is description","this is solution hash"); - // cannot raise dispute multiple times - await assertRevert(marketInstance.raiseDispute(1400000000000,"raise dispute","this is description","this is solution hash")); - await assertRevert(marketInstance.resolveDispute(true, 100)); - let winningOption_af = await marketInstance.getMarketResults() - console.log("winningOption",winningOption_af[0]/1) - let proposalId = await gv.getProposalLength()-1; - console.log("proposalId",proposalId/1) - let userBalBefore = await plotusToken.balanceOf(ab1); - console.log("balance before accept proposal",userBalBefore/1) - - await plotusToken.approve(tokenController.address, "100000000000000000000000",{from : dr1}); - await tokenController.lock("0x4452","30000000000000000000000",(86400*20),{from : dr1}); - - await plotusToken.approve(tokenController.address, "100000000000000000000000",{from : dr2}); - await tokenController.lock("0x4452","30000000000000000000000",(86400*20),{from : dr2}); - - await assertRevert(gv.submitVote(proposalId, 1, {from:dr3})) //reverts as tokens not locked - - await plotusToken.approve(tokenController.address, "100000000000000000000000",{from : dr3}); - await tokenController.lock("0x4452","30000000000000000000000",(86400*20),{from : dr3}); - let roles = await mr.roles(dr3); - assert.equal(roles[0]/1, 2, "Not added to Token holder"); - assert.equal(roles[1]/1, 3, "Not added to DR"); - await increaseTime(604800); - await gv.closeProposal(proposalId); - // let data = await plotusNewInstance.marketDisputeData(marketInstance.address) - // assert.equal(data[0], proposalId,"dispute proposal mismatch"); - // let marketDetails = await plotusNewInstance.getMarketDetails(marketInstance.address); - // assert.equal(marketDetails[7]/1, 3, "status not updated"); - - let userBalAfter = await plotusToken.balanceOf(ab1); - console.log("balance before accept proposal",userBalAfter/1) - let winningOption_afterVote = await marketInstance.getMarketResults() - assert.equal(winningOption_af[0]/1, winningOption_afterVote[0]/1); - console.log("winningOption After accept proposal",winningOption_afterVote[0]/1); - }); -}); -contract("Market", ([ab1, ab2, ab3, ab4, dr1, dr2, dr3, notMember]) => { - it("2.if DR panel rejects", async () => { - masterInstance = await OwnedUpgradeabilityProxy.deployed(); - masterInstance = await Master.at(masterInstance.address); - let tokenControllerAdd = await masterInstance.getLatestAddress(web3.utils.toHex("TC")); - tokenController = await TokenController.at(tokenControllerAdd); - let plotusNewAddress = await masterInstance.getLatestAddress(web3.utils.toHex("PL")); - let plotusNewInstance = await Plotus.at(plotusNewAddress); - MockUniswapRouterInstance = await MockUniswapRouter.deployed(); - const openMarkets = await plotusNewInstance.getOpenMarkets(); - marketConfig = await plotusNewInstance.marketUtility(); - marketConfig = await MarketConfig.at(marketConfig); - marketInstance = await Market.at(openMarkets["_openMarkets"][0]); - await marketConfig.setOptionPrice(1, 9); - await marketConfig.setOptionPrice(2, 18); - await marketConfig.setOptionPrice(3, 27); - await increaseTime(10001); - assert.ok(marketInstance); - let nxmToken = await PlotusToken.deployed(); - let address = await masterInstance.getLatestAddress(web3.utils.toHex("GV")); - let plotusToken = await PlotusToken.deployed(); - gv = await Governance.at(address); - address = await masterInstance.getLatestAddress(web3.utils.toHex("PC")); - let pc = await ProposalCategory.at(address); - address = await masterInstance.getLatestAddress(web3.utils.toHex("MR")); - mr = await MemberRoles.at(address); - let tc = await TokenController.at(await masterInstance.getLatestAddress(web3.utils.toHex("MR"))); - - await plotusToken.approve(mr.address, "100000000000000000000000"); - - await plotusToken.transfer(ab2, "50000000000000000000000"); - await plotusToken.transfer(ab3, "50000000000000000000000"); - await plotusToken.transfer(ab4, "50000000000000000000000"); - await plotusToken.transfer(dr1, "50000000000000000000000"); - await plotusToken.transfer(dr2, "50000000000000000000000"); - await plotusToken.transfer(dr3, "50000000000000000000000"); - await MockUniswapRouterInstance.setPrice("1000000000000000"); - await marketConfig.setPrice("1000000000000000"); - await plotusToken.approve(tokenController.address, "100000000000000000000"); - await marketInstance.placePrediction(plotusToken.address, "100000000000000000000", 1, 1); - - await increaseTime(7201); - await marketInstance.calculatePredictionResult(100000000000); - //can raise dispute in cooling period and stake - await plotusToken.approve(tokenController.address, "10000000000000000000000"); - await marketInstance.raiseDispute(1400000000000,"raise dispute","this is description","this is solution hash"); - await increaseTime(901); - // cannot raise dispute if market cool time is over - await plotusToken.approve(tokenController.address, "10000000000000000000000"); - await assertRevert(marketInstance.raiseDispute(1400000000000,"raise dispute","this is description","this is solution hash")); - - let plotusContractBalanceBefore = await plotusToken.balanceOf(plotusNewInstance.address); - let winningOption_before = await marketInstance.getMarketResults() - console.log("winningOption",winningOption_before[0]/1) - let proposalId = await gv.getProposalLength()-1; - console.log("proposalId",proposalId/1) - let userBalBefore = await plotusToken.balanceOf(ab1); - console.log("balance before reject proposal",userBalBefore/1) - await plotusToken.approve(tokenController.address, "100000000000000000000000",{from : dr1}); - await tokenController.lock("0x4452","5000000000000000000000",(86400*20),{from : dr1}); - - await plotusToken.approve(tokenController.address, "100000000000000000000000",{from : dr2}); - await tokenController.lock("0x4452","5000000000000000000000",(86400*20),{from : dr2}); - - await plotusToken.approve(tokenController.address, "100000000000000000000000",{from : dr3}); - await tokenController.lock("0x4452","5000000000000000000000",(86400*100),{from : dr3}); - await gv.submitVote(proposalId, 0, {from:dr1}); - await gv.submitVote(proposalId, 0, {from:dr2}); - await gv.submitVote(proposalId, 0, {from:dr3}); - await increaseTime(9 * 86401); - await gv.closeProposal(proposalId); - await increaseTime(86401); - let proposal = await gv.proposal(proposalId); - assert.isAbove((proposal[2])/1,3); - let plotusContractBalanceAfter = await plotusToken.balanceOf(plotusNewInstance.address); - // assert.isAbove(plotusContractBalanceBefore/1, plotusContractBalanceAfter/1); - //InIncentives will be transferred to governance 100 tokens i.e 100000000000000000000 - assert.equal((plotusContractBalanceAfter/1), plotusContractBalanceBefore/1 - 500000000000000000000, "Tokens staked for dispute not burned"); - - let winningOption_afterVote = await marketInstance.getMarketResults(); - assert.equal(winningOption_before[0]/1, winningOption_afterVote[0]/1); - console.log("winningOption After reject proposal",winningOption_afterVote[0]/1); - }); - - it("Should not burn DR member's tokens if invalid code is passed in proposal", async function() { - let tokensLockedOfDR1Before = await tokenController.tokensLocked(dr1, toHex("DR")); - action = "burnLockedTokens(address,bytes32,uint256)" - let actionHash = encode(action, dr1, toHex("PR"), "2000000000000000000000"); - let p = await gv.getProposalLength(); - await gv.createProposal("proposal", "proposal", "proposal", 0); - await gv.categorizeProposal(p, 11, 0); - await gv.submitProposalWithSolution(p, "proposal", actionHash); - let members = await mr.members(2); - let iteration = 0; - await gv.submitVote(p, 1); - await gv.submitVote(p, 1, {from:ab2}); - await gv.submitVote(p, 1, {from:ab3}); - await gv.submitVote(p, 1, {from:ab4}); - - await increaseTime(604800); - await gv.closeProposal(p); - let proposal = await gv.proposal(p); - assert.equal(proposal[2].toNumber(), 3); - await increaseTime(86400); - await gv.triggerAction(p); - let proposalActionStatus = await gv.proposalActionStatus(p); - assert.equal(proposalActionStatus/1, 1, "Not executed"); - let tokensLockedOfDR1after = await tokenController.tokensLocked(dr1, web3.utils.toHex("DR")); - assert.equal(tokensLockedOfDR1after/1, tokensLockedOfDR1Before/1, "burned"); - }); - - it("Should burn partial DR member's tokens if lock period is not completed", async function() { - - assert.equal((await tokenController.tokensLockedAtTime(dr3,toHex("DR"),await latestTime())),"5000000000000000000000"); - let tokensLockedOfDR1Before = await tokenController.tokensLockedAtTime(dr3, web3.utils.toHex("DR"), await latestTime()); - action = "burnLockedTokens(address,bytes32,uint256)" - let actionHash = encode(action, dr3, toHex("DR"), "2000000000000000000000"); - let p = await gv.getProposalLength(); - await gv.createProposal("proposal", "proposal", "proposal", 0); - await gv.categorizeProposal(p, 11, 0); - await gv.submitProposalWithSolution(p, "proposal", actionHash); - let members = await mr.members(2); - let iteration = 0; - await gv.submitVote(p, 1); - await gv.submitVote(p, 1, {from:ab2}); - await gv.submitVote(p, 1, {from:ab3}); - await gv.submitVote(p, 1, {from:ab4}); - await gv.submitVote(p, 1, {from:dr1}); - await gv.submitVote(p, 1, {from:dr2}); - await gv.submitVote(p, 1, {from:dr3}); - - await increaseTime(604800); - await gv.closeProposal(p); - let proposal = await gv.proposal(p); - assert.equal(proposal[2].toNumber(), 3); - await increaseTime(86400); - await gv.triggerAction(p); - let proposalActionStatus = await gv.proposalActionStatus(p); - assert.equal(proposalActionStatus/1, 3, "Not executed"); - let tokensLockedOfDR1after = await tokenController.tokensLockedAtTime(dr3, web3.utils.toHex("DR"),await latestTime()); - assert.equal(tokensLockedOfDR1after/1, tokensLockedOfDR1Before/1 - 2000000000000000000000, "Not burned"); - }); - - it("Should burn all DR member's tokens if lock period is not completed", async function() { - - assert.equal((await tokenController.tokensLockedAtTime(dr3,toHex("DR"),await latestTime())),"3000000000000000000000"); - let tokensLockedOfDR1Before = await tokenController.tokensLockedAtTime(dr3, web3.utils.toHex("DR"), await latestTime()); - action = "burnLockedTokens(address,bytes32,uint256)" - let actionHash = encode(action, dr3, toHex("DR"), "3000000000000000000000"); - let p = await gv.getProposalLength(); - await gv.createProposal("proposal", "proposal", "proposal", 0); - await gv.categorizeProposal(p, 11, 0); - await gv.submitProposalWithSolution(p, "proposal", actionHash); - let members = await mr.members(2); - let iteration = 0; - await gv.submitVote(p, 1); - await gv.submitVote(p, 1, {from:ab2}); - await gv.submitVote(p, 1, {from:ab3}); - await gv.submitVote(p, 1, {from:ab4}); - await gv.submitVote(p, 1, {from:dr1}); - await gv.submitVote(p, 1, {from:dr2}); - await gv.submitVote(p, 1, {from:dr3}); - - await increaseTime(604800); - await gv.closeProposal(p); - let proposal = await gv.proposal(p); - assert.equal(proposal[2].toNumber(), 3); - await increaseTime(86400); - await gv.triggerAction(p); - let proposalActionStatus = await gv.proposalActionStatus(p); - assert.equal(proposalActionStatus/1, 3, "Not executed"); - let tokensLockedOfDR1after = await tokenController.tokensLockedAtTime(dr3, web3.utils.toHex("DR"),await latestTime()); - assert.equal(tokensLockedOfDR1after/1, tokensLockedOfDR1Before/1 - 3000000000000000000000, "Not burned"); - }); - - it("Increase time to complete lock period", async function() { - await increaseTime(8640000); - // await tokenController.unlock(dr3); - }); - - it("Should not burn DR member's tokens if lock period is completed", async function() { - - assert.equal((await tokenController.tokensLockedAtTime(dr1,toHex("DR"),await latestTime())),0); - let tokensLockedOfDR1Before = await tokenController.tokensLocked(dr1, toHex("DR")); - action = "burnLockedTokens(address,bytes32,uint256)" - let actionHash = encode(action, dr1, toHex("DR"), "2000000000000000000000"); - let p = await gv.getProposalLength(); - await gv.createProposal("proposal", "proposal", "proposal", 0); - await gv.categorizeProposal(p, 11, 0); - await gv.submitProposalWithSolution(p, "proposal", actionHash); - let members = await mr.members(2); - let iteration = 0; - await gv.submitVote(p, 1); - await gv.submitVote(p, 1, {from:ab2}); - await gv.submitVote(p, 1, {from:ab3}); - await gv.submitVote(p, 1, {from:ab4}); - - await increaseTime(604800); - await gv.closeProposal(p); - let proposal = await gv.proposal(p); - assert.equal(proposal[2].toNumber(), 3); - await increaseTime(86400); - await gv.triggerAction(p); - let proposalActionStatus = await gv.proposalActionStatus(p); - assert.equal(proposalActionStatus/1, 1, "Not executed"); - let tokensLockedOfDR1after = await tokenController.tokensLocked(dr1, web3.utils.toHex("DR")); - assert.equal(tokensLockedOfDR1after/1, tokensLockedOfDR1Before/1, "burned"); - }); - -}); \ No newline at end of file diff --git a/test/05_disputeResolutionNew.js b/test/05_disputeResolutionNew.js new file mode 100644 index 000000000..76d7d476f --- /dev/null +++ b/test/05_disputeResolutionNew.js @@ -0,0 +1,565 @@ +const { assert } = require("chai"); +const OwnedUpgradeabilityProxy = artifacts.require('OwnedUpgradeabilityProxy'); +const Master = artifacts.require("Master"); +const PlotusToken = artifacts.require("MockPLOT"); +const TokenController = artifacts.require("MockTokenController"); +const MockchainLinkBTC = artifacts.require("MockChainLinkAggregator"); +const Governance = artifacts.require("Governance"); +const AllMarkets = artifacts.require("MockAllMarkets"); +const MarketConfig = artifacts.require("MockConfig"); +const ProposalCategory = artifacts.require('ProposalCategory'); +const MemberRoles = artifacts.require('MockMemberRoles'); +const BLOT = artifacts.require("BLOT"); +const MarketCreationRewards = artifacts.require("MarketCreationRewards"); +const MockChainLinkGasPriceAgg = artifacts.require("MockChainLinkGasPriceAgg"); +const gvProposal = require("./utils/gvProposal.js").gvProposalWithIncentiveViaTokenHolder; +const increaseTime = require("./utils/increaseTime.js").increaseTime; +const latestTime = require("./utils/latestTime.js").latestTime; +const encode = require("./utils/encoder.js").encode; +const encode1 = require("./utils/encoder.js").encode1; +const encode3 = require("./utils/encoder.js").encode3; +const {toHex, toWei, toChecksumAddress} = require('./utils/ethTools'); +const { assertRevert } = require('./utils/assertRevert'); +const signAndExecuteMetaTx = require("./utils/signAndExecuteMetaTx.js").signAndExecuteMetaTx; +let privateKeyList = ["fb437e3e01939d9d4fef43138249f23dc1d0852e69b0b5d1647c087f869fabbd","7c85a1f1da3120c941b83d71a154199ee763307683f206b98ad92c3b4e0af13e","ecc9b35bf13bd5459350da564646d05c5664a7476fe5acdf1305440f88ed784c","f4470c3fca4dbef1b2488d016fae25978effc586a1f83cb29ac8cb6ab5bc2d50","141319b1a84827e1046e93741bf8a9a15a916d49684ab04925ac4ce4573eea23","d54b606094287758dcf19064a8d91c727346aadaa9388732e73c4315b7c606f9","49030e42ce4152e715a7ddaa10e592f8e61d00f70ef11f48546711f159d985df","b96761b1e7ebd1e8464a78a98fe52f53ce6035c32b4b2b12307a629a551ff7cf","d4786e2581571c863c7d12231c3afb6d4cef390c0ac9a24b243293721d28ea95","ed28e3d3530544f1cf2b43d1956b7bd13b63c612d963a8fb37387aa1a5e11460","05b127365cf115d4978a7997ee98f9b48f0ddc552b981c18aa2ee1b3e6df42c6","9d11dd6843f298b01b34bd7f7e4b1037489871531d14b58199b7cba1ac0841e6","f79e90fa4091de4fc2ec70f5bf67b24393285c112658e0d810e6bd711387fbb9","99f1fc0f09230ce745b6a256ba7082e6e51a2907abda3d9e735a5c8188bb4ba1","477f86cce983b9c91a36fdcd4a7ce21144a08dee9b1aafb91b9c70e57f717ce6","b03d2e6bb4a7d71c66a66ff9e9c93549cae4b593f634a4ea2a1f79f94200f5b4","9ddc0f53a81e631dcf39d5155f41ec12ed551b731efc3224f410667ba07b37dc","cf087ff9ae7c9954ad8612d071e5cdf34a6024ee1ae477217639e63a802a53dd","b64f62b94babb82cc78d3d1308631ae221552bb595202fc1d267e1c29ce7ba60","a91e24875f8a534497459e5ccb872c4438be3130d8d74b7e1104c5f94cdcf8c2","4f49f3d029eeeb3fed14d59625acd088b6b34f3b41c527afa09d29e4a7725c32","179795fd7ac7e7efcba3c36d539a1e8659fb40d77d0a3fab2c25562d99793086","4ba37d0b40b879eceaaca2802a1635f2e6d86d5c31e3ff2d2fd13e68dd2a6d3d","6b7f5dfba9cd3108f1410b56f6a84188eee23ab48a3621b209a67eea64293394","870c540da9fafde331a3316cee50c17ad76ddb9160b78b317bef2e6f6fc4bac0","470b4cccaea895d8a5820aed088357e380d66b8e7510f0a1ea9b575850160241","8a55f8942af0aec1e0df3ab328b974a7888ffd60ded48cc6862013da0f41afbc","2e51e8409f28baf93e665df2a9d646a1bf9ac8703cbf9a6766cfdefa249d5780","99ef1a23e95910287d39493d8d9d7d1f0b498286f2b1fdbc0b01495f10cf0958","6652200c53a4551efe2a7541072d817562812003f9d9ef0ec17995aa232378f8","39c6c01194df72dda97da2072335c38231ced9b39afa280452afcca901e73643","12097e411d948f77b7b6fa4656c6573481c1b4e2864c1fca9d5b296096707c45","cbe53bf1976aee6cec830a848c6ac132def1503cffde82ccfe5bd15e75cbaa72","eeab5dcfff92dbabb7e285445aba47bd5135a4a3502df59ac546847aeb5a964f","5ea8279a578027abefab9c17cef186cccf000306685e5f2ee78bdf62cae568dd","0607767d89ad9c7686dbb01b37248290b2fa7364b2bf37d86afd51b88756fe66","e4fd5f45c08b52dae40f4cdff45e8681e76b5af5761356c4caed4ca750dc65cd","145b1c82caa2a6d703108444a5cf03e9cb8c3cd3f19299582a564276dbbba734","736b22ec91ae9b4b2b15e8d8c220f6c152d4f2228f6d46c16e6a9b98b4733120","ac776cb8b40f92cdd307b16b83e18eeb1fbaa5b5d6bd992b3fda0b4d6de8524c","65ba30e2202fdf6f37da0f7cfe31dfb5308c9209885aaf4cef4d572fd14e2903","54e8389455ec2252de063e83d3ce72529d674e6d2dc2070661f01d4f76b63475","fbbbfb525dd0255ee332d51f59648265aaa20c2e9eff007765cf4d4a6940a849","8de5e418f34d04f6ea947ce31852092a24a705862e6b810ca9f83c2d5f9cda4d","ea6040989964f012fd3a92a3170891f5f155430b8bbfa4976cde8d11513b62d9","14d94547b5deca767137fbd14dae73e888f3516c742fad18b83be333b38f0b88","47f05203f6368d56158cda2e79167777fc9dcb0c671ef3aabc205a1636c26a29"]; +let gv,masterInstance, tokenController, mr; +contract("Market", ([ab1, ab2, ab3, ab4, dr1, dr2, dr3, notMember]) => { + it("1.if DR panel accepts", async () => { + masterInstance = await OwnedUpgradeabilityProxy.deployed(); + masterInstance = await Master.at(masterInstance.address); + let tokenControllerAdd = await masterInstance.getLatestAddress(web3.utils.toHex("TC")); + tokenController = await TokenController.at(tokenControllerAdd); + marketConfig = await MarketConfig.at(await masterInstance.getLatestAddress(web3.utils.toHex("MU"))); + governance = await masterInstance.getLatestAddress(web3.utils.toHex("GV")); + governance = await Governance.at(governance); + + let allMarkets = await masterInstance.getLatestAddress(web3.utils.toHex("AM")); + allMarkets = await AllMarkets.at(allMarkets); + + await increaseTime(3600*4); + let nxmToken = await PlotusToken.deployed(); + let address = await masterInstance.getLatestAddress(web3.utils.toHex("GV")); + let plotusToken = await PlotusToken.deployed(); + await marketConfig.setAssetPlotConversionRate(plotusToken.address, 1); + gv = await Governance.at(address); + address = await masterInstance.getLatestAddress(web3.utils.toHex("PC")); + pc = await ProposalCategory.at(address); + address = await masterInstance.getLatestAddress(web3.utils.toHex("MR")); + mr = await MemberRoles.at(address); + let tc = await TokenController.at(await masterInstance.getLatestAddress(web3.utils.toHex("MR"))); + marketIncentives = await MarketCreationRewards.at(await masterInstance.getLatestAddress(web3.utils.toHex("MC"))); + await plotusToken.approve(mr.address, "10000000000000000000000"); + await plotusToken.transfer(marketIncentives.address, "100000000000000000000"); + let marketIncentivesBalanceBefore = await plotusToken.balanceOf(marketIncentives.address); + await allMarkets.createMarket(0,0); + await plotusToken.transfer(ab2, "50000000000000000000000"); + await plotusToken.transfer(ab3, "50000000000000000000000"); + await plotusToken.transfer(ab4, "50000000000000000000000"); + await plotusToken.transfer(dr1, "50000000000000000000000"); + await plotusToken.transfer(dr2, "50000000000000000000000"); + await plotusToken.transfer(dr3, "50000000000000000000000"); + await plotusToken.approve(tokenController.address, "100000000000000000000"); + await plotusToken.approve(allMarkets.address, "10000000000000000000000"); + // Cannot raise dispute if there is no participation + await assertRevert(allMarkets.raiseDispute(7, 1400000000000,"raise dispute","this is description","this is solution hash")); + await marketConfig.setNextOptionPrice(9); + await marketConfig.setPrice(toWei(0.01)); + await allMarkets.depositAndPlacePrediction("10000000000000000000000", 7, plotusToken.address, 100*1e8, 1); + // cannot raise dispute if market is open + await plotusToken.approve(allMarkets.address, "10000000000000000000000"); + await assertRevert(allMarkets.raiseDispute(7, 1400000000000,"raise dispute","this is description","this is solution hash")); + + await increaseTime(3601); + // cannot raise dispute if market is closed but result is not out + await plotusToken.approve(allMarkets.address, "10000000000000000000000"); + await assertRevert(allMarkets.raiseDispute(7, 1400000000000,"raise dispute","this is description","this is solution hash")); + + await increaseTime(8*3600); + await allMarkets.postResultMock("10000000000000000000", 7); + let allMarketsBalanceBefore = await plotusToken.balanceOf(allMarkets.address); + let marketIncentivesBalance = await plotusToken.balanceOf(marketIncentives.address); + assert.equal(marketIncentivesBalance*1, marketIncentivesBalanceBefore/1+3.6*1e18); + // cannot raise dispute with less than minimum stake + await plotusToken.approve(allMarkets.address, "10000000000000000000000"); + await assertRevert(allMarkets.raiseDispute(7, 1400000000000,"raise dispute","this is description","this is solution hash",{from : notMember})); + //can raise dispute in cooling period and stake + await plotusToken.approve(allMarkets.address, "10000000000000000000000"); + let functionSignature = encode3("raiseDispute(uint256,uint256,string,string,string)",7,1,"raise dispute","this is description","this is solution hash"); + await signAndExecuteMetaTx( + privateKeyList[0], + ab1, + functionSignature, + allMarkets + ); + // await allMarkets.raiseDispute(7,1,"raise dispute","this is description","this is solution hash"); + // cannot raise dispute multiple times + await assertRevert(allMarkets.raiseDispute(7, 1400000000000,"raise dispute","this is description","this is solution hash")); + await assertRevert(allMarkets.resolveDispute(7, 100)); + let winningOption_af = await allMarkets.getMarketResults(7) + let proposalId = await gv.getProposalLength()-1; + let userBalBefore = await plotusToken.balanceOf(ab1); + + await plotusToken.approve(tokenController.address, "100000000000000000000000",{from : dr1}); + await tokenController.lock("0x4452","30000000000000000000000",(86400*20),{from : dr1}); + + await plotusToken.approve(tokenController.address, "100000000000000000000000",{from : dr2}); + await tokenController.lock("0x4452","30000000000000000000000",(86400*20),{from : dr2}); + + await assertRevert(gv.submitVote(proposalId, 1, {from:dr3})) //reverts as tokens not locked + + await plotusToken.approve(tokenController.address, "100000000000000000000000",{from : dr3}); + await tokenController.lock("0x4452","30000000000000000000000",(86400*20),{from : dr3}); + let roles = await mr.roles(dr3); + assert.equal(roles[0]/1, 2, "Not added to Token holder"); + assert.equal(roles[1]/1, 3, "Not added to DR"); + await gv.submitVote(proposalId, 1, {from:dr1}); + await gv.submitVote(proposalId, 1, {from:dr2}); + await gv.submitVote(proposalId, 1, {from:dr3}); + await increaseTime(604800); + await gv.closeProposal(proposalId); + let winningOption_afterVote = await allMarkets.getMarketResults(7); + assert.notEqual(winningOption_af[0]/1, winningOption_afterVote[0]/1); + assert.equal(winningOption_afterVote[0]/1, 1); + + let allMarketsBalanceAfter = await plotusToken.balanceOf(allMarkets.address); + let commission = 3.6 * 1e18; + // let marketCreatorIncentives = 99.95*((0.05)/100) * 1e18; + let marketIncentivesBalanceAfter = await plotusToken.balanceOf(marketIncentives.address); + assert.equal(marketIncentivesBalanceBefore*1 + commission*1, marketIncentivesBalanceAfter*1 + (toWei(100))*1); + + assert.equal((allMarketsBalanceAfter/1), allMarketsBalanceBefore/1, "Tokens staked for dispute not burned"); + // let data = await plotusNewInstance.marketDisputeData(marketInstance.address) + // assert.equal(data[0], proposalId,"dispute proposal mismatch"); + // let marketDetails = await plotusNewInstance.getMarketDetails(marketInstance.address); + // assert.equal(marketDetails[7]/1, 3, "status not updated"); + let proposalActionStatus = await gv.proposalActionStatus(proposalId); + assert.equal(proposalActionStatus/1, 3); + let userBalAfter = await plotusToken.balanceOf(ab1); + assert.equal(userBalAfter/1e18, userBalBefore/1e18+500); + }); +}); + +contract("Market", ([ab1, ab2, ab3, ab4, dr1, dr2, dr3, notMember]) => { + it("1.DR panel accepts and proper transfer of assets between AllMarkets and MarketCreationRewards", async () => { + masterInstance = await OwnedUpgradeabilityProxy.deployed(); + masterInstance = await Master.at(masterInstance.address); + let tokenControllerAdd = await masterInstance.getLatestAddress(web3.utils.toHex("TC")); + tokenController = await TokenController.at(tokenControllerAdd); + marketConfig = await masterInstance.getLatestAddress(web3.utils.toHex("MU")); + marketConfig = await MarketConfig.at(marketConfig); + governance = await masterInstance.getLatestAddress(web3.utils.toHex("GV")); + governance = await Governance.at(governance); + + let allMarkets = await masterInstance.getLatestAddress(web3.utils.toHex("AM")); + allMarkets = await AllMarkets.at(allMarkets); + + + + await increaseTime(3600*4); + let nxmToken = await PlotusToken.deployed(); + let address = await masterInstance.getLatestAddress(web3.utils.toHex("GV")); + let plotusToken = await PlotusToken.deployed(); + await marketConfig.setAssetPlotConversionRate(plotusToken.address, 1); + gv = await Governance.at(address); + address = await masterInstance.getLatestAddress(web3.utils.toHex("PC")); + pc = await ProposalCategory.at(address); + address = await masterInstance.getLatestAddress(web3.utils.toHex("MR")); + mr = await MemberRoles.at(address); + let tc = await TokenController.at(await masterInstance.getLatestAddress(web3.utils.toHex("MR"))); + marketIncentives = await MarketCreationRewards.at(await masterInstance.getLatestAddress(web3.utils.toHex("MC"))); + await plotusToken.transfer(dr1, "50000000000000000000000"); + await plotusToken.approve(allMarkets.address, "30000000000000000000000", {from:dr1}); + // await plotusToken.transfer(marketIncentives.address, "100000000000000000000"); + let marketIncentivesBalanceBefore = await plotusToken.balanceOf(marketIncentives.address); + await allMarkets.createMarket(0,0,{from:dr1}); + await plotusToken.approve(mr.address, "10000000000000000000000"); + + await plotusToken.transfer(ab2, "50000000000000000000000"); + await plotusToken.transfer(ab3, "50000000000000000000000"); + await plotusToken.transfer(ab4, "50000000000000000000000"); + await plotusToken.transfer(dr2, "50000000000000000000000"); + await plotusToken.transfer(dr3, "50000000000000000000000"); + await marketConfig.setPrice("1000000000000000"); + await plotusToken.approve(tokenController.address, "100000000000000000000"); + await plotusToken.approve(allMarkets.address, "30000000000000000000000"); + // Cannot raise dispute if there is no participation + await assertRevert(allMarkets.raiseDispute(7, 1400000000000,"raise dispute","this is description","this is solution hash")); + await marketConfig.setNextOptionPrice(9); + await marketConfig.setPrice(toWei(0.01)); + await allMarkets.depositAndPlacePrediction("10000000000000000000000", 7, plotusToken.address, 100*1e8, 1); + await allMarkets.depositAndPlacePrediction("20000000000000000000000", 7, plotusToken.address, 200*1e8, 3); + // cannot raise dispute if market is open + await plotusToken.approve(allMarkets.address, "10000000000000000000000"); + await assertRevert(allMarkets.raiseDispute(7, 1400000000000,"raise dispute","this is description","this is solution hash")); + + await increaseTime(3601); + // cannot raise dispute if market is closed but result is not out + await plotusToken.approve(allMarkets.address, "10000000000000000000000"); + await assertRevert(allMarkets.raiseDispute(7, 1400000000000,"raise dispute","this is description","this is solution hash")); + + await increaseTime(8*3600); + let allMarketsBalanceBefore = await plotusToken.balanceOf(allMarkets.address); + await allMarkets.postResultMock("10000000000000000000", 7); + let marketIncentivesBalance = await plotusToken.balanceOf(marketIncentives.address); + let commission = 7.2 * 1e18; + let rewardPool = 163.33333333*1e18; + let marketCreatorIncentive = 0 * 0.5/100; + assert.equal(marketIncentivesBalance*1, marketIncentivesBalanceBefore/1 + marketCreatorIncentive + commission*1); + // cannot raise dispute with less than minimum stake + await plotusToken.approve(allMarkets.address, "10000000000000000000000"); + await assertRevert(allMarkets.raiseDispute(7, 1400000000000,"raise dispute","this is description","this is solution hash",{from : notMember})); + //can raise dispute in cooling period and stake + await plotusToken.approve(allMarkets.address, "10000000000000000000000"); + await plotusToken.transfer(marketIncentives.address, "100000000000000000000"); + await allMarkets.raiseDispute(7,1,"raise dispute","this is description","this is solution hash"); + // cannot raise dispute multiple times + await assertRevert(allMarkets.raiseDispute(7, 1400000000000,"raise dispute","this is description","this is solution hash")); + await assertRevert(allMarkets.resolveDispute(7, 100)); + let winningOption_af = await allMarkets.getMarketResults(7) + let proposalId = await gv.getProposalLength()-1; + let userBalBefore = await plotusToken.balanceOf(ab1); + + await plotusToken.approve(tokenController.address, "100000000000000000000000",{from : dr1}); + await tokenController.lock("0x4452","30000000000000000000000",(86400*20),{from : dr1}); + + await plotusToken.approve(tokenController.address, "100000000000000000000000",{from : dr2}); + await tokenController.lock("0x4452","30000000000000000000000",(86400*20),{from : dr2}); + + await assertRevert(gv.submitVote(proposalId, 1, {from:dr3})) //reverts as tokens not locked + + await plotusToken.approve(tokenController.address, "100000000000000000000000",{from : dr3}); + await tokenController.lock("0x4452","30000000000000000000000",(86400*20),{from : dr3}); + let roles = await mr.roles(dr3); + assert.equal(roles[0]/1, 2, "Not added to Token holder"); + assert.equal(roles[1]/1, 3, "Not added to DR"); + await gv.submitVote(proposalId, 1, {from:dr1}); + await gv.submitVote(proposalId, 1, {from:dr2}); + await gv.submitVote(proposalId, 1, {from:dr3}); + await increaseTime(604800); + await gv.closeProposal(proposalId); + + let winningOption_afterVote = await allMarkets.getMarketResults(7); + assert.notEqual(winningOption_af[0]/1, winningOption_afterVote[0]/1); + assert.equal(winningOption_afterVote[0]/1, 1); + + let allMarketsBalanceAfter = await plotusToken.balanceOf(allMarkets.address); + rewardPool = 261.33333333*1e18; + marketCreatorIncentive = rewardPool * 0.5/100; + // let marketCreatorIncentives = 99.95*((0.05)/100) * 1e18; + let marketIncentivesBalanceAfter = await plotusToken.balanceOf(marketIncentives.address); + assert.equal(marketIncentivesBalanceBefore*1 + commission*1, marketIncentivesBalanceAfter*1); + + assert.equal((allMarketsBalanceAfter/1), allMarketsBalanceBefore/1 , "Tokens staked for dispute not burned"); + // let data = await plotusNewInstance.marketDisputeData(marketInstance.address) + // assert.equal(data[0], proposalId,"dispute proposal mismatch"); + // let marketDetails = await plotusNewInstance.getMarketDetails(marketInstance.address); + // assert.equal(marketDetails[7]/1, 3, "status not updated"); + let proposalActionStatus = await gv.proposalActionStatus(proposalId); + assert.equal(proposalActionStatus/1, 3); + let userBalAfter = await plotusToken.balanceOf(ab1); + assert.equal(~~(userBalAfter/1e16), ~~(userBalBefore/1e16)+50000); + }); +}); +contract("Market", ([ab1, ab2, ab3, ab4, dr1, dr2, dr3, notMember]) => { + it("1.if quorum not reached proposal should be rejected", async () => { + masterInstance = await OwnedUpgradeabilityProxy.deployed(); + masterInstance = await Master.at(masterInstance.address); + let tokenControllerAdd = await masterInstance.getLatestAddress(web3.utils.toHex("TC")); + tokenController = await TokenController.at(tokenControllerAdd); + marketConfig = await masterInstance.getLatestAddress(web3.utils.toHex("MU")); + marketConfig = await MarketConfig.at(marketConfig); + governance = await masterInstance.getLatestAddress(web3.utils.toHex("GV")); + governance = await Governance.at(governance); + + let allMarkets = await masterInstance.getLatestAddress(web3.utils.toHex("AM")); + allMarkets = await AllMarkets.at(allMarkets); + marketIncentives = await MarketCreationRewards.at(await masterInstance.getLatestAddress(web3.utils.toHex("MC"))); + + + await increaseTime(3600*4); + await allMarkets.createMarket(0,0); + let nxmToken = await PlotusToken.deployed(); + let address = await masterInstance.getLatestAddress(web3.utils.toHex("GV")); + let plotusToken = await PlotusToken.deployed(); + await marketConfig.setAssetPlotConversionRate(plotusToken.address, 1); + await plotusToken.transfer(marketIncentives.address, "100000000000000000000"); + gv = await Governance.at(address); + address = await masterInstance.getLatestAddress(web3.utils.toHex("PC")); + pc = await ProposalCategory.at(address); + address = await masterInstance.getLatestAddress(web3.utils.toHex("MR")); + mr = await MemberRoles.at(address); + let tc = await TokenController.at(await masterInstance.getLatestAddress(web3.utils.toHex("MR"))); + await plotusToken.approve(mr.address, "10000000000000000000000"); + + await plotusToken.transfer(ab2, "50000000000000000000000"); + await plotusToken.transfer(ab3, "50000000000000000000000"); + await plotusToken.transfer(ab4, "50000000000000000000000"); + await plotusToken.transfer(dr1, "50000000000000000000000"); + await plotusToken.transfer(dr2, "50000000000000000000000"); + await plotusToken.transfer(dr3, "50000000000000000000000"); + await marketConfig.setPrice("1000000000000000"); + await marketConfig.setNextOptionPrice(2); + await plotusToken.approve(allMarkets.address, "100000000000000000000"); + await allMarkets.depositAndPlacePrediction("100000000000000000000", 7, plotusToken.address, 100*1e8, 1); + // cannot raise dispute if market is open + await plotusToken.approve(allMarkets.address, "10000000000000000000000"); + await assertRevert(allMarkets.raiseDispute(7, 1400000000000,"raise dispute","this is description","this is solution hash")); + + await increaseTime(3601); + // cannot raise dispute if market is closed but result is not out + await plotusToken.approve(tokenController.address, "10000000000000000000000"); + await assertRevert(allMarkets.raiseDispute(7, 1400000000000,"raise dispute","this is description","this is solution hash")); + + await increaseTime(3600*8); + await allMarkets.postResultMock(100000000000, 7); + // cannot raise dispute with less than minimum stake + await plotusToken.approve(tokenController.address, "10000000000000000000000"); + await assertRevert(allMarkets.raiseDispute(7, 1400000000000,"raise dispute","this is description","this is solution hash",{from : notMember})); + //can raise dispute in cooling period and stake + await plotusToken.approve(tokenController.address, "10000000000000000000000"); + await allMarkets.raiseDispute(7, 1400000000000,"raise dispute","this is description","this is solution hash"); + // cannot raise dispute multiple times + await assertRevert(allMarkets.raiseDispute(7, 1400000000000,"raise dispute","this is description","this is solution hash")); + await assertRevert(allMarkets.resolveDispute(7, 100)); + let winningOption_af = await allMarkets.getMarketResults(7) + let proposalId = await gv.getProposalLength()-1; + let userBalBefore = await plotusToken.balanceOf(ab1); + + await plotusToken.approve(tokenController.address, "100000000000000000000000",{from : dr1}); + await tokenController.lock("0x4452","30000000000000000000000",(86400*20),{from : dr1}); + + await plotusToken.approve(tokenController.address, "100000000000000000000000",{from : dr2}); + await tokenController.lock("0x4452","30000000000000000000000",(86400*20),{from : dr2}); + + await assertRevert(gv.submitVote(proposalId, 1, {from:dr3})) //reverts as tokens not locked + + await plotusToken.approve(tokenController.address, "100000000000000000000000",{from : dr3}); + await tokenController.lock("0x4452","30000000000000000000000",(86400*20),{from : dr3}); + let roles = await mr.roles(dr3); + assert.equal(roles[0]/1, 2, "Not added to Token holder"); + assert.equal(roles[1]/1, 3, "Not added to DR"); + await increaseTime(604800); + await gv.closeProposal(proposalId); + // let data = await plotusNewInstance.marketDisputeData(marketInstance.address) + // assert.equal(data[0], proposalId,"dispute proposal mismatch"); + // let marketDetails = await plotusNewInstance.getMarketDetails(marketInstance.address); + // assert.equal(marketDetails[7]/1, 3, "status not updated"); + + let userBalAfter = await plotusToken.balanceOf(ab1); + let winningOption_afterVote = await allMarkets.getMarketResults(7) + assert.equal(userBalAfter/1e18, userBalBefore/1e18, "Tokens not burnt"); + assert.equal(winningOption_af[0]/1, winningOption_afterVote[0]/1); + }); +}); +contract("Market", ([ab1, ab2, ab3, ab4, dr1, dr2, dr3, notMember]) => { + it("2.if DR panel rejects", async () => { + masterInstance = await OwnedUpgradeabilityProxy.deployed(); + masterInstance = await Master.at(masterInstance.address); + let tokenControllerAdd = await masterInstance.getLatestAddress(web3.utils.toHex("TC")); + tokenController = await TokenController.at(tokenControllerAdd); + marketConfig = await masterInstance.getLatestAddress(web3.utils.toHex("MU")); + marketConfig = await MarketConfig.at(marketConfig); + governance = await masterInstance.getLatestAddress(web3.utils.toHex("GV")); + governance = await Governance.at(governance); + + let allMarkets = await masterInstance.getLatestAddress(web3.utils.toHex("AM")); + allMarkets = await AllMarkets.at(allMarkets); + + await increaseTime(3600*4); + await allMarkets.createMarket(0,0); + let nxmToken = await PlotusToken.deployed(); + let address = await masterInstance.getLatestAddress(web3.utils.toHex("GV")); + let plotusToken = await PlotusToken.deployed(); + await marketConfig.setAssetPlotConversionRate(plotusToken.address, 1); + + marketIncentives = await MarketCreationRewards.at(await masterInstance.getLatestAddress(web3.utils.toHex("MC"))); + await plotusToken.transfer(marketIncentives.address, "100000000000000000000"); + + gv = await Governance.at(address); + address = await masterInstance.getLatestAddress(web3.utils.toHex("PC")); + pc = await ProposalCategory.at(address); + address = await masterInstance.getLatestAddress(web3.utils.toHex("MR")); + mr = await MemberRoles.at(address); + let tc = await TokenController.at(await masterInstance.getLatestAddress(web3.utils.toHex("MR"))); + + await plotusToken.approve(mr.address, "100000000000000000000000"); + + await plotusToken.transfer(ab2, "50000000000000000000000"); + await plotusToken.transfer(ab3, "50000000000000000000000"); + await plotusToken.transfer(ab4, "50000000000000000000000"); + await plotusToken.transfer(dr1, "50000000000000000000000"); + await plotusToken.transfer(dr2, "50000000000000000000000"); + await plotusToken.transfer(dr3, "50000000000000000000000"); + await marketConfig.setPrice("1000000000000000"); + await marketConfig.setNextOptionPrice(2); + await plotusToken.approve(allMarkets.address, "100000000000000000000"); + await allMarkets.depositAndPlacePrediction("100000000000000000000", 7, plotusToken.address, 100*1e8, 1); + + await increaseTime(3600*8); + await allMarkets.postResultMock(100000000000, 7); + //can raise dispute in cooling period and stake + await plotusToken.approve(allMarkets.address, "10000000000000000000000"); + let allMarketsBalanceBefore = await plotusToken.balanceOf(allMarkets.address); + await allMarkets.raiseDispute(7, 1400000000000,"raise dispute","this is description","this is solution hash"); + await increaseTime(901); + // cannot raise dispute if market cool time is over + await plotusToken.approve(allMarkets.address, "10000000000000000000000"); + await assertRevert(allMarkets.raiseDispute(7, 1400000000000,"raise dispute","this is description","this is solution hash")); + + let plotusContractBalanceBefore = await plotusToken.balanceOf(allMarkets.address); + let winningOption_before = await allMarkets.getMarketResults(7) + let proposalId = await gv.getProposalLength()-1; + let userBalBefore = await plotusToken.balanceOf(ab1); + await plotusToken.approve(tokenController.address, "100000000000000000000000",{from : dr1}); + await tokenController.lock("0x4452","5000000000000000000000",(86400*20),{from : dr1}); + + await plotusToken.approve(tokenController.address, "100000000000000000000000",{from : dr2}); + await tokenController.lock("0x4452","5000000000000000000000",(86400*20),{from : dr2}); + + await plotusToken.approve(tokenController.address, "100000000000000000000000",{from : dr3}); + await tokenController.lock("0x4452","5000000000000000000000",(86400*100),{from : dr3}); + await gv.submitVote(proposalId, 0, {from:dr1}); + await gv.submitVote(proposalId, 0, {from:dr2}); + await gv.submitVote(proposalId, 0, {from:dr3}); + await increaseTime(9 * 86401); + await gv.closeProposal(proposalId); + await increaseTime(86401); + let proposal = await gv.proposal(proposalId); + assert.isAbove((proposal[2])/1,3); + let plotusContractBalanceAfter = await plotusToken.balanceOf(allMarkets.address); + // assert.isAbove(plotusContractBalanceBefore/1, plotusContractBalanceAfter/1); + //Incentives will be burnt: 500 tokens i.e 500000000000000000000 + assert.equal((plotusContractBalanceAfter/1e18).toFixed(2), (plotusContractBalanceBefore/1e18 - 500).toFixed(2), "Tokens staked for dispute not burned"); + let allMarketsBalanceAfter = await plotusToken.balanceOf(allMarkets.address); + allMarketsBalanceAfter = allMarketsBalanceAfter.toString(); + allMarketsBalanceBefore = allMarketsBalanceBefore.toString(); + assert.equal((allMarketsBalanceAfter), allMarketsBalanceBefore, "Tokens staked for dispute not burned"); + let userBalAfter = await plotusToken.balanceOf(ab1); + + assert.equal(userBalAfter/1e18, userBalBefore/1e18, "Tokens not burnt"); + let winningOption_afterVote = await allMarkets.getMarketResults(7); + assert.equal(winningOption_before[0]/1, winningOption_afterVote[0]/1); + }); + + it("Should not burn DR member's tokens if invalid code is passed in proposal", async function() { + let tokensLockedOfDR1Before = await tokenController.tokensLocked(dr1, toHex("DR")); + action = "burnLockedTokens(address,bytes32,uint256)" + let actionHash = encode(action, dr1, toHex("PR"), "2000000000000000000000"); + let p = await gv.getProposalLength(); + await gv.createProposal("proposal", "proposal", "proposal", 0); + await gv.categorizeProposal(p, 10, 0); + await gv.submitProposalWithSolution(p, "proposal", actionHash); + let members = await mr.members(2); + let iteration = 0; + await gv.submitVote(p, 1); + // await gv.submitVote(p, 1, {from:ab2}); + // await gv.submitVote(p, 1, {from:ab3}); + // await gv.submitVote(p, 1, {from:ab4}); + + await increaseTime(604800); + await gv.closeProposal(p); + let proposal = await gv.proposal(p); + assert.equal(proposal[2].toNumber(), 3); + await increaseTime(86400); + await gv.triggerAction(p); + let proposalActionStatus = await gv.proposalActionStatus(p); + assert.equal(proposalActionStatus/1, 1, "Not executed"); + let tokensLockedOfDR1after = await tokenController.tokensLocked(dr1, web3.utils.toHex("DR")); + assert.equal(tokensLockedOfDR1after/1, tokensLockedOfDR1Before/1, "burned"); + }); + + it("Should burn partial DR member's tokens if lock period is not completed", async function() { + + assert.equal((await tokenController.tokensLockedAtTime(dr3,toHex("DR"),await latestTime())),"5000000000000000000000"); + let tokensLockedOfDR1Before = await tokenController.tokensLockedAtTime(dr3, web3.utils.toHex("DR"), await latestTime()); + action = "burnLockedTokens(address,bytes32,uint256)" + let actionHash = encode(action, dr3, toHex("DR"), "2000000000000000000000"); + let p = await gv.getProposalLength(); + await gv.createProposal("proposal", "proposal", "proposal", 0); + await gv.categorizeProposal(p, 10, 0); + await gv.submitProposalWithSolution(p, "proposal", actionHash); + let members = await mr.members(2); + let iteration = 0; + await gv.submitVote(p, 1); + // await gv.submitVote(p, 1, {from:ab2}); + // await gv.submitVote(p, 1, {from:ab3}); + // await gv.submitVote(p, 1, {from:ab4}); + // await gv.submitVote(p, 1, {from:dr1}); + // await gv.submitVote(p, 1, {from:dr2}); + // await gv.submitVote(p, 1, {from:dr3}); + + await increaseTime(604800); + await gv.closeProposal(p); + let proposal = await gv.proposal(p); + assert.equal(proposal[2].toNumber(), 3); + let proposalActionStatus = await gv.proposalActionStatus(p); + assert.equal(proposalActionStatus/1, 3, "Not executed"); + let tokensLockedOfDR1after = await tokenController.tokensLockedAtTime(dr3, web3.utils.toHex("DR"),await latestTime()); + assert.equal(tokensLockedOfDR1after/1, tokensLockedOfDR1Before/1 - 2000000000000000000000, "Not burned"); + }); + + it("Should burn all DR member's tokens if lock period is not completed", async function() { + + assert.equal((await tokenController.tokensLockedAtTime(dr3,toHex("DR"),await latestTime()))/1,"3000000000000000000000"); + let tokensLockedOfDR1Before = await tokenController.tokensLockedAtTime(dr3, web3.utils.toHex("DR"), await latestTime()); + action = "burnLockedTokens(address,bytes32,uint256)" + let actionHash = encode(action, dr3, toHex("DR"), "3000000000000000000000"); + let p = await gv.getProposalLength(); + await gv.createProposal("proposal", "proposal", "proposal", 0); + await gv.categorizeProposal(p, 10, 0); + await gv.submitProposalWithSolution(p, "proposal", actionHash); + let members = await mr.members(2); + let iteration = 0; + await gv.submitVote(p, 1); + // await gv.submitVote(p, 1, {from:ab2}); + // await gv.submitVote(p, 1, {from:ab3}); + // await gv.submitVote(p, 1, {from:ab4}); + // await gv.submitVote(p, 1, {from:dr1}); + // await gv.submitVote(p, 1, {from:dr2}); + // await gv.submitVote(p, 1, {from:dr3}); + + await increaseTime(604800); + await gv.closeProposal(p); + let proposal = await gv.proposal(p); + assert.equal(proposal[2].toNumber(), 3); + let proposalActionStatus = await gv.proposalActionStatus(p); + assert.equal(proposalActionStatus/1, 3, "Not executed"); + let tokensLockedOfDR1after = await tokenController.tokensLockedAtTime(dr3, web3.utils.toHex("DR"),await latestTime()); + assert.equal(tokensLockedOfDR1after/1, tokensLockedOfDR1Before/1 - 3000000000000000000000, "Not burned"); + }); + + it("Increase time to complete lock period", async function() { + await increaseTime(8640000); + // await tokenController.unlock(dr3); + }); + + it("Should not burn DR member's tokens if lock period is completed", async function() { + + assert.equal((await tokenController.tokensLockedAtTime(dr1,toHex("DR"),await latestTime())),0); + let tokensLockedOfDR1Before = await tokenController.tokensLocked(dr1, toHex("DR")); + action = "burnLockedTokens(address,bytes32,uint256)" + let actionHash = encode(action, dr1, toHex("DR"), "2000000000000000000000"); + let p = await gv.getProposalLength(); + await gv.createProposal("proposal", "proposal", "proposal", 0); + await gv.categorizeProposal(p, 10, 0); + await gv.submitProposalWithSolution(p, "proposal", actionHash); + let members = await mr.members(2); + let iteration = 0; + await gv.submitVote(p, 1); + // await gv.submitVote(p, 1, {from:ab2}); + // await gv.submitVote(p, 1, {from:ab3}); + // await gv.submitVote(p, 1, {from:ab4}); + + await increaseTime(604800); + await gv.closeProposal(p); + let proposal = await gv.proposal(p); + assert.equal(proposal[2].toNumber(), 3); + await increaseTime(86400); + await gv.triggerAction(p); + let proposalActionStatus = await gv.proposalActionStatus(p); + assert.equal(proposalActionStatus/1, 1, "Not executed"); + let tokensLockedOfDR1after = await tokenController.tokensLocked(dr1, web3.utils.toHex("DR")); + assert.equal(tokensLockedOfDR1after/1, tokensLockedOfDR1Before/1, "burned"); + }); + +}); \ No newline at end of file diff --git a/test/06_GovernanceCategory.test.js b/test/06_GovernanceCategoryNew.test.js similarity index 54% rename from test/06_GovernanceCategory.test.js rename to test/06_GovernanceCategoryNew.test.js index d5f2f7671..9867721b6 100644 --- a/test/06_GovernanceCategory.test.js +++ b/test/06_GovernanceCategoryNew.test.js @@ -1,13 +1,12 @@ const Governance = artifacts.require('Governance'); +const AllMarkets = artifacts.require('AllMarkets'); +const MarketCreationRewards = artifacts.require('MarketCreationRewards'); const ProposalCategory = artifacts.require('ProposalCategory'); const MemberRoles = artifacts.require('MemberRoles'); const Master = artifacts.require('Master'); const TokenController = artifacts.require('TokenController'); -const Plotus = artifacts.require("MarketRegistry"); const MarketConfig = artifacts.require('MarketUtility'); const PlotusToken = artifacts.require("MockPLOT"); -const Market = artifacts.require('MockMarket'); -const DummyMockMarket = artifacts.require('DummyMockMarket'); const OwnedUpgradeabilityProxy = artifacts.require('OwnedUpgradeabilityProxy'); const gvProposal = require('./utils/gvProposal.js').gvProposalWithIncentiveViaTokenHolder; const assertRevert = require("./utils/assertRevert.js").assertRevert; @@ -24,6 +23,7 @@ let mr; let tc; let ms; let pl; +let allMarkets, mcr; let marketConfig; let plotTok; let snapshotId; @@ -47,198 +47,128 @@ contract('Configure Global Parameters', accounts => { address = await ms.getLatestAddress('0x4d52'); mr = await MemberRoles.at(address); tc = await TokenController.at(await ms.getLatestAddress('0x5443')); - pl = await Plotus.at(await ms.getLatestAddress(toHex('PL'))); - marketConfig = await MarketConfig.at(await pl.marketUtility()); + marketConfig = await MarketConfig.at(await ms.getLatestAddress(toHex("MU"))); + mcr = await MarketCreationRewards.at(await ms.getLatestAddress(toHex("MC"))); + allMarkets = await AllMarkets.at(await ms.getLatestAddress(toHex("AM"))); plotTok = await PlotusToken.deployed(); - await pl.sendTransaction({from: ab1, value: toWei(5)}); - await pl.sendTransaction({from: newAB, value: toWei(10)}); - await plotTok.transfer(pl.address, toWei(20)); + await plotTok.transfer(allMarkets.address, toWei(20)); await plotTok.transfer(newAB, toWei(20)); }); describe('Testing Governanace Test Cases', function() { - - it('Should Not Update Market Config if zero address passed', async function() { - let params = []; - params.push((await marketConfig.getFeedAddresses())); - params.push((await marketConfig.getFeedAddresses())); - params.push(plotTok.address); - let oldImplementation = await OwnedUpgradeabilityProxy.at(await pl.marketUtility()); - oldImplementation = await oldImplementation.implementation(); - let actionHash = encode( - 'upgradeContractImplementation(address,address)', - marketConfig.address, - 0x0000000000000000000000000000000000000000 - ); - await gvProposal( - 6, - actionHash, - await MemberRoles.at(await ms.getLatestAddress(toHex('MR'))), - gv, - 2, - 0 - ); - let proxyCon = await OwnedUpgradeabilityProxy.at(await pl.marketUtility()); - assert.equal(await proxyCon.implementation(), oldImplementation); - }); - it('Should Update Market Config', async function() { - let params = []; - params.push((await marketConfig.getFeedAddresses())); - params.push((await marketConfig.getFeedAddresses())); - params.push(plotTok.address); - params.push((await marketConfig.getFeedAddresses())); - let newMarketConfig = await MarketConfig.new(params); - let actionHash = encode( - 'upgradeContractImplementation(address,address)', - marketConfig.address, - newMarketConfig.address - ); - await gvProposal( - 6, - actionHash, - await MemberRoles.at(await ms.getLatestAddress(toHex('MR'))), - gv, - 2, - 0 - ); - let proxyCon = await OwnedUpgradeabilityProxy.at(await pl.marketUtility()); - assert.equal(await proxyCon.implementation(), newMarketConfig.address); - }); - - it('Should Update Market Implementation', async function() { - let newMaketImpl = await Market.new(); - let actionHash + it('Should Update Governance to new contract', async function() { + let newGV = await Governance.new() actionHash = encode1( - ['uint256[]', 'address[]'], + ['bytes2[]', 'address[]'], [ - [0,1], - [newMaketImpl.address, newMaketImpl.address] + [toHex('GV')], + [newGV.address] ] ); + await gvProposal( - 5, - actionHash, - await MemberRoles.at(await ms.getLatestAddress(toHex('MR'))), - gv, - 2, - 0 - ); - }); - - it('Should Not Update Market Implementation of invalid paramters are passed', async function() { - let newMaketImpl = await Market.new(); - let actionHash - actionHash = encode1( - ['uint256[]', 'address[]'], - [ - [0], - [newMaketImpl.address, newMaketImpl.address] - ] - ); - await gvProposal( - 5, + 6, actionHash, await MemberRoles.at(await ms.getLatestAddress(toHex('MR'))), gv, 2, - 0 + 0, accounts[0] ); + let proxy = await OwnedUpgradeabilityProxy.at(gv.address); + assert.equal(await proxy.implementation(), newGV.address); }); - - it('Should Update Existing Markets Implementation', async function() { - let newMarket = await DummyMockMarket.new(); - let existingMarkets = await pl.getOpenMarkets(); + + it('Should Not Update Market Config if zero address passed', async function() { + let oldImplementation = await OwnedUpgradeabilityProxy.at(marketConfig.address); + oldImplementation = await oldImplementation.implementation(); let actionHash = encode( 'upgradeContractImplementation(address,address)', - existingMarkets[0][0], - newMarket.address + marketConfig.address, + 0x0000000000000000000000000000000000000000 ); await gvProposal( - 6, + 5, actionHash, await MemberRoles.at(await ms.getLatestAddress(toHex('MR'))), gv, 2, - 0 + 0, accounts[0] ); - let proxyCon = await OwnedUpgradeabilityProxy.at(existingMarkets[0][0]); - assert.equal(await proxyCon.implementation(), newMarket.address); - newMarket = await DummyMockMarket.at(existingMarkets[0][0]); - assert.equal(await newMarket.dummyFunction(), 123); + let proxyCon = await OwnedUpgradeabilityProxy.at(marketConfig.address); + assert.equal(await proxyCon.implementation(), oldImplementation); }); it('Should Pause Market Creation', async function() { - assert.equal(await pl.marketCreationPaused(), false); + assert.equal(await allMarkets.marketCreationPaused(), false); let actionHash = encode( 'pauseMarketCreation()' ); await gvProposal( - 17, + 16, actionHash, await MemberRoles.at(await ms.getLatestAddress(toHex('MR'))), gv, 2, 0 ); - assert.equal(await pl.marketCreationPaused(), true); + assert.equal(await allMarkets.marketCreationPaused(), true); }); it('Should stay Pause Market Creation if already paused', async function() { - assert.equal(await pl.marketCreationPaused(), true); + assert.equal(await allMarkets.marketCreationPaused(), true); let actionHash = encode( 'pauseMarketCreation()' ); await gvProposal( - 17, + 16, actionHash, await MemberRoles.at(await ms.getLatestAddress(toHex('MR'))), gv, 2, 0 ); - assert.equal(await pl.marketCreationPaused(), true); + assert.equal(await allMarkets.marketCreationPaused(), true); }); it('Should Resume Market Creation', async function() { - assert.equal(await pl.marketCreationPaused(), true); + assert.equal(await allMarkets.marketCreationPaused(), true); let actionHash = encode( 'resumeMarketCreation()' ); await gvProposal( - 18, + 17, actionHash, await MemberRoles.at(await ms.getLatestAddress(toHex('MR'))), gv, 2, 0 ); - assert.equal(await pl.marketCreationPaused(), false); + assert.equal(await allMarkets.marketCreationPaused(), false); }); it('Should stay Resume Market Creation if already resumed', async function() { - assert.equal(await pl.marketCreationPaused(), false); + assert.equal(await allMarkets.marketCreationPaused(), false); let actionHash = encode( 'resumeMarketCreation()' ); await gvProposal( - 18, + 17, actionHash, await MemberRoles.at(await ms.getLatestAddress(toHex('MR'))), gv, 2, 0 ); - assert.equal(await pl.marketCreationPaused(), false); + assert.equal(await allMarkets.marketCreationPaused(), false); }); - it('Transfer Plotus Assets(PlotusToken)', async function() { - let plbalPlot = await plotTok.balanceOf(pl.address); - await plotTok.burnTokens(pl.address, plbalPlot); - await plotTok.transfer(pl.address, 1000000000000); - plbalPlot = await plotTok.balanceOf(pl.address); + let plbalPlot = await plotTok.balanceOf(mcr.address); + await plotTok.burnTokens(mcr.address, plbalPlot); + await plotTok.transfer(mcr.address, 1000000000000); + plbalPlot = await plotTok.balanceOf(mcr.address); let userbalPlot = await plotTok.balanceOf(newAB); let actionHash = encode( 'transferAssets(address,address,uint256)', @@ -248,46 +178,23 @@ contract('Configure Global Parameters', accounts => { ); let pId = await gv.getProposalLength(); await gvProposal( - 19, + 18, actionHash, await MemberRoles.at(await ms.getLatestAddress(toHex('MR'))), gv, 2, 0 ); - let plbalPlotAfter = await plotTok.balanceOf(pl.address); + let plbalPlotAfter = await plotTok.balanceOf(mcr.address); let userbalPlotAfter = await plotTok.balanceOf(newAB); assert.equal(plbalPlot/1 - plbalPlotAfter/1, 1000000000000); assert.equal(userbalPlotAfter/1 - userbalPlot/1, 1000000000000); }); - it('Transfer Plotus Assets(ETH)', async function() { - let plbalEth = await web3.eth.getBalance(pl.address); - let userbalEth = await web3.eth.getBalance(newAB); - let actionHash = encode( - 'transferAssets(address,address,uint256)', - "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", - newAB, - toWei(10) - ); - await gvProposal( - 19, - actionHash, - await MemberRoles.at(await ms.getLatestAddress(toHex('MR'))), - gv, - 2, - 0 - ); - let plbalEthAfter = await web3.eth.getBalance(pl.address); - let userbalEthAfter = await web3.eth.getBalance(newAB); - assert.equal(plbalEth - plbalEthAfter, toWei(10)); - assert.equal(userbalEthAfter/1e18 - userbalEth/1e18, 10); - }); - it('Should not allow create a proposal in category raiseDispute directly', async function() { let p = await gv.getProposalLength(); await gv.createProposal("proposal", "proposal", "proposal", 0); - await assertRevert(gv.categorizeProposal(p, 10, 0)); + await assertRevert(gv.categorizeProposal(p, 9, 0)); }); it('Should Whitelist sponsor', async function() { @@ -297,7 +204,7 @@ contract('Configure Global Parameters', accounts => { newAB ); await gvProposal( - 23, + 21, actionHash, await MemberRoles.at(await ms.getLatestAddress(toHex('MR'))), gv, @@ -316,7 +223,7 @@ contract('Configure Global Parameters', accounts => { await gv.createProposal("proposal", "proposal", "proposal", 0); let canClose = await gv.canCloseProposal(p); assert.equal(parseFloat(canClose),0); - await gv.categorizeProposal(p, 24, 0); + await gv.categorizeProposal(p, 25, 0); await assertRevert(gv.submitProposalWithSolution(p, "proposal", "0x1234")); await gv.submitProposalWithSolution(p, "proposal", actionHash); await gv.submitVote(p, 1); @@ -336,7 +243,7 @@ contract('Configure Global Parameters', accounts => { ab1 ); await gvProposal( - 12, + 11, actionHash, await MemberRoles.at(await ms.getLatestAddress(toHex('MR'))), gv, @@ -347,23 +254,23 @@ contract('Configure Global Parameters', accounts => { assert.equal(await mr.checkRole(newAB, 1), true); }); - it('Should Swap AB Member without whitelisting proposal', async function() { + // it('Should Swap AB Member without whitelisting proposal', async function() { - assert.equal(await mr.checkRole(newAB, 1), true); - assert.equal(await mr.checkRole(ab1, 1), false); - let actionHash = encode( - 'swapABMember(address,address)', - ab1, - newAB - ); - let proposalId = await gv.getProposalLength(); - await gv.createProposalwithSolution("Add new member", "Add new member", "hash", 12, "", actionHash) - await gv.submitVote(proposalId/1, 1); - await increaseTime(604810); - await gv.closeProposal(proposalId/1); - assert.equal(await mr.checkRole(ab1, 1), true); - assert.equal(await mr.checkRole(newAB, 1), false); - }); + // assert.equal(await mr.checkRole(newAB, 1), true); + // assert.equal(await mr.checkRole(ab1, 1), false); + // let actionHash = encode( + // 'swapABMember(address,address)', + // ab1, + // newAB + // ); + // let proposalId = await gv.getProposalLength(); + // await gv.createProposalwithSolution("Add new member", "Add new member", "hash", 11, "", actionHash) + // await gv.submitVote(proposalId/1, 1); + // await increaseTime(604810); + // await gv.closeProposal(proposalId/1); + // assert.equal(await mr.checkRole(ab1, 1), true); + // assert.equal(await mr.checkRole(newAB, 1), false); + // }); }); after(async function () { diff --git a/test/07_MasterTestcases.test.js b/test/07_MasterTestcases.test.js index d61b288b7..b4b21c9c5 100644 --- a/test/07_MasterTestcases.test.js +++ b/test/07_MasterTestcases.test.js @@ -3,7 +3,9 @@ const MemberRoles = artifacts.require('MemberRoles'); const Governance = artifacts.require('Governance'); const ProposalCategory = artifacts.require('ProposalCategory'); const TokenController = artifacts.require("MockTokenController"); -const Plotus = artifacts.require("MockMarketRegistry"); +const AllMarkets = artifacts.require("AllMarkets"); +const MarketUtility = artifacts.require("MarketUtility"); +const MarketCreationRewards = artifacts.require("MarketCreationRewards"); const PlotusToken = artifacts.require("MockPLOT"); const OwnedUpgradeabilityProxy = artifacts.require('OwnedUpgradeabilityProxy'); const NewProxyInternalContract = artifacts.require('NewProxyInternalContract'); @@ -28,7 +30,7 @@ let memberRoles; let gov; let propCat; let nxmMas; -let pl; +let allMarkets; let plotTok; let snapshotId; @@ -46,16 +48,147 @@ contract('Master', function(accounts) { propCat = await ProposalCategory.at(await ms.getLatestAddress(toHex('PC'))); memberRoles = await MemberRoles.at(await ms.getLatestAddress(toHex('MR'))); gov = await Governance.at(await ms.getLatestAddress(toHex('GV'))); - pl = await Plotus.at(await ms.getLatestAddress(toHex('PL'))); + allMarkets = await AllMarkets.at(await ms.getLatestAddress(toHex('AM'))); }); + describe('Negative Test Cases', function() { + it('Upgrade contract should revert if called directly', async function() { + await assertRevert( + ms.upgradeMultipleImplementations([toHex('GV')], [gov.address]) + ); + }); + it('Upgrade contract should revert if array length is different for contract code and address', async function() { + actionHash = encode1( + ['bytes2[]', 'address[]'], + [ + [toHex('GV')], + [gov.address, allMarkets.address] + ] + ); + + await gvProp( + 6, + actionHash, + await MemberRoles.at(await ms.getLatestAddress(toHex('MR'))), + await Governance.at(await ms.getLatestAddress(toHex('GV'))), + 2, + 0 + ); + }); + it('Add internal contract should revert if called directly', async function() { + await assertRevert( + ms.addNewContract(toHex('PS'), allMarkets.address) + ); + }); + it('Add internal contract should revert if new contract code already exist', async function() { + actionHash = encode1( + ['bytes2', 'address'], + [ + toHex('GV'), + gov.address + ] + ); + await gvProp( + 8, + actionHash, + await MemberRoles.at(await ms.getLatestAddress(toHex('MR'))), + await Governance.at(await ms.getLatestAddress(toHex('GV'))), + 2, + 0 + ); + }); + it('Add internal contract should revert if new contract address is null', async function() { + actionHash = encode1( + ['bytes2', 'address'], + [ + toHex('PS'), + ZERO_ADDRESS + ] + ); + await gvProp( + 8, + actionHash, + await MemberRoles.at(await ms.getLatestAddress(toHex('MR'))), + await Governance.at(await ms.getLatestAddress(toHex('GV'))), + 2, + 0 + ); + }); + it('Add internal contract should revert if new contract code is MS', async function() { + actionHash = encode1( + ['bytes2', 'address'], + [ + toHex('MS'), + gov.address + ] + ); + await gvProp( + 8, + actionHash, + await MemberRoles.at(await ms.getLatestAddress(toHex('MR'))), + await Governance.at(await ms.getLatestAddress(toHex('GV'))), + 2, + 0 + ); + }); + it('Upgrade contract implementation should revert if new address is null', async function() { + oldGv = await Governance.at(await ms.getLatestAddress(toHex('GV'))); + oldMR = await MemberRoles.at(await ms.getLatestAddress(toHex('MR'))); + gvProxy = await OwnedUpgradeabilityProxy.at( + await ms.getLatestAddress(toHex('GV')) + ); + let gvImplementationAdd = await gvProxy.implementation(); + oldPC = await ProposalCategory.at( + await ms.getLatestAddress(toHex('PC')) + ); + + let catId = 6; + + actionHash = encode1( + ['bytes2[]', 'address[]'], + [[toHex('GV')], [ZERO_ADDRESS]] + ); + + await gvProp( + catId, + actionHash, + await MemberRoles.at(await ms.getLatestAddress(toHex('MR'))), + await Governance.at(await ms.getLatestAddress(toHex('GV'))), + 2, + 0 + ); + assert.equal( + gvImplementationAdd, + await gvProxy.implementation() + ); + }); + it('Should revert if caller is not proxyOwner', async function() { + mas = await Master.new(); + mas = await OwnedUpgradeabilityProxy.new(mas.address); + mas = await Master.at(mas.address); + await assertRevert( + mas.initiateMaster([mas.address, mas.address, mas.address], mas.address, mas.address, mas.address, {from: newOwner}) + ); + }); + it('Should revert if length of implementation array and contract array are not same', async function() { + await assertRevert( + mas.initiateMaster([mas.address, mas.address, mas.address], mas.address, mas.address, mas.address) + ); + }); + it('Should revert if master already initiated', async function() { + await assertRevert( + ms.initiateMaster([mas.address, mas.address, mas.address], mas.address, mas.address, mas.address) + ); + }); + }); + describe('Update master address', function() { it('Update master address', async function() { let newMaster = await Master.new(); let actionHash = encode1(['address'], [newMaster.address]); await gvProp( - 8, + 7, actionHash, await MemberRoles.at(await ms.getLatestAddress(toHex('MR'))), gov, @@ -69,11 +202,11 @@ contract('Master', function(accounts) { it('Create a sample proposal after updating master', async function() { let actionHash = encode( 'updateUintParameters(bytes8,uint256)', - toHex('MAXDRFT'), - 7 + toHex('REJCOUNT'), + 2 ); await gvProp( - 13, + 12, actionHash, await MemberRoles.at(await ms.getLatestAddress(toHex('MR'))), gov, @@ -81,14 +214,16 @@ contract('Master', function(accounts) { 0 ); assert.equal( - (await gov.getUintParameters(toHex('MAXDRFT')))[1].toNumber(), - 7 + (await gov.getUintParameters(toHex('REJCOUNT')))[1].toNumber(), + 2 ); }); - it('Sending funds to funds to PL', async function() { - await pl.sendTransaction({from: owner, value: toWei(10)}); - await plotTok.transfer(pl.address, toWei(1)); + it('Sending funds to funds to MCR', async function() { + mcr = await MarketCreationRewards.at( + await ms.getLatestAddress(toHex('MC')) + ); + await plotTok.transfer(mcr.address, toWei(1)); await plotTok.transfer(tc.address, toWei(1)); }); @@ -102,33 +237,40 @@ contract('Master', function(accounts) { oldPC = await ProposalCategory.at( await ms.getLatestAddress(toHex('PC')) ); - oldPL = await Plotus.at( - await ms.getLatestAddress(toHex('PL')) + oldAM = await AllMarkets.at( + await ms.getLatestAddress(toHex('AM')) + ); + oldMCR = await MarketCreationRewards.at( + await ms.getLatestAddress(toHex('MC')) + ); + oldUtility = await MarketUtility.at( + await ms.getLatestAddress(toHex('MU')) ); let tcbalPlot = await plotTok.balanceOf( await ms.getLatestAddress(toHex('TC')) ); let plbalPlot = await plotTok.balanceOf( - await ms.getLatestAddress(toHex('PL')) + await ms.getLatestAddress(toHex('MC')) ); - let plbalEth = await web3.eth.getBalance(pl.address); let proposalDetails = await oldGv.proposal(1); let totalSupply = await oldTC.totalSupply(); let catDetails = await oldPC.category(5); let members = await oldMR.members(2); - let openMarkets = await oldPL.getOpenMarkets(); - let catId = 7; - let newPlotus = await Plotus.new(); + let relayerFeePercent = (await oldAM.getUintParameters(toHex("RELF")))[1]; + let catId = 6; + let newAllMarkets = await AllMarkets.new(); await increaseTime(100); let newGV = await Governance.new(); let newPC = await ProposalCategory.new(); let newMR = await MemberRoles.new(); let newTC = await TokenController.new(); + let newMU = await MarketUtility.new(); + let newMC = await MarketCreationRewards.new(); actionHash = encode1( ['bytes2[]', 'address[]'], [ - [toHex('GV'), toHex('PC'), toHex('MR'), toHex('TC'), toHex('PL')], - [newGV.address, newPC.address, newMR.address, newTC.address, newPlotus.address] + [toHex('GV'), toHex('PC'), toHex('MR'), toHex('TC'), toHex('AM'), toHex("MU"), toHex("MC")], + [newGV.address, newPC.address, newMR.address, newTC.address, newAllMarkets.address, newMU.address, newMC.address] ] ); @@ -153,8 +295,14 @@ contract('Master', function(accounts) { let oldTCImpl = await OwnedUpgradeabilityProxy.at( await ms.getLatestAddress(toHex('TC')) ); - let oldPLImpl = await OwnedUpgradeabilityProxy.at( - await ms.getLatestAddress(toHex('PL')) + let oldAMImpl = await OwnedUpgradeabilityProxy.at( + await ms.getLatestAddress(toHex('AM')) + ); + let oldMUImpl = await OwnedUpgradeabilityProxy.at( + await ms.getLatestAddress(toHex('MU')) + ); + let oldMCImpl = await OwnedUpgradeabilityProxy.at( + await ms.getLatestAddress(toHex('MC')) ); // Checking Upgraded Contract addresses @@ -162,7 +310,9 @@ contract('Master', function(accounts) { assert.equal(newPC.address, await oldPCImpl.implementation()); assert.equal(newMR.address, await oldMRImpl.implementation()); assert.equal(newTC.address, await oldTCImpl.implementation()); - assert.equal(newPlotus.address, await oldPLImpl.implementation()); + assert.equal(newMU.address, await oldMUImpl.implementation()); + assert.equal(newMC.address, await oldMCImpl.implementation()); + assert.equal(newAllMarkets.address, await oldAMImpl.implementation()); oldGv = await Governance.at(await ms.getLatestAddress(toHex('GV'))); oldMR = await MemberRoles.at(await ms.getLatestAddress(toHex('MR'))); @@ -171,7 +321,9 @@ contract('Master', function(accounts) { assert.equal(ms.address, await oldMR.masterAddress()); assert.equal(ms.address, await oldTC.masterAddress()); assert.equal(ms.address, await oldPC.masterAddress()); - assert.equal(ms.address, await oldPL.masterAddress()); + assert.equal(ms.address, await oldAM.masterAddress()); + assert.equal(ms.address, await oldMCR.masterAddress()); + assert.equal(ms.address, await oldUtility.masterAddress()); // Checking Funds transfer in upgraded Contracts assert.equal( @@ -180,12 +332,10 @@ contract('Master', function(accounts) { ); assert.equal( - (await plotTok.balanceOf(await ms.getLatestAddress(toHex('PL')))) / 1, + (await plotTok.balanceOf(await ms.getLatestAddress(toHex('MC')))) / 1, plbalPlot / 1 ); - assert.equal((await web3.eth.getBalance(pl.address)) / 1, plbalEth / 1); - // Checking getters in upgraded Contracts assert.equal( (await oldGv.proposal(1)).toString(), @@ -194,7 +344,7 @@ contract('Master', function(accounts) { assert.equal((await oldMR.members(2)).toString(), members.toString()); assert.equal((await oldTC.totalSupply()) / 1, totalSupply / 1); assert.equal((await oldPC.category(5)).toString(), catDetails.toString()); - assert.equal((await oldPL.getOpenMarkets()).toString(), openMarkets.toString()); + assert.equal(((await oldAM.getUintParameters(toHex("RELF")))[1]).toString(), relayerFeePercent.toString()); }); it('Add new Proxy Internal contract', async function() { let nic = await NewProxyInternalContract.new(); @@ -207,7 +357,7 @@ contract('Master', function(accounts) { ); await gvProp( - 9, + 8, actionHash, await MemberRoles.at(await ms.getLatestAddress(toHex('MR'))), await Governance.at(await ms.getLatestAddress(toHex('GV'))), @@ -243,137 +393,6 @@ contract('Master', function(accounts) { assert.equal(ms.address, await gov.ms()); assert.equal(ms.address, await mrProxy.masterAddress()); assert.equal(ms.address, await catProxy.masterAddress()); - assert.equal(ms.address, await pl.masterAddress()); - }); - }); - describe('Negative Test Cases', function() { - it('Upgrade contract should revert if called directly', async function() { - await assertRevert( - ms.upgradeMultipleImplementations([toHex('GV')], [gov.address]) - ); - }); - it('Upgrade contract should revert if array length is different for contract code and address', async function() { - actionHash = encode1( - ['bytes2[]', 'address[]'], - [ - [toHex('GV')], - [gov.address, pl.address] - ] - ); - - await gvProp( - 7, - actionHash, - await MemberRoles.at(await ms.getLatestAddress(toHex('MR'))), - await Governance.at(await ms.getLatestAddress(toHex('GV'))), - 2, - 0 - ); - }); - it('Add internal contract should revert if called directly', async function() { - await assertRevert( - ms.addNewContract(toHex('PS'), pl.address) - ); - }); - it('Add internal contract should revert if new contract code already exist', async function() { - actionHash = encode1( - ['bytes2', 'address'], - [ - toHex('GV'), - gov.address - ] - ); - await gvProp( - 9, - actionHash, - await MemberRoles.at(await ms.getLatestAddress(toHex('MR'))), - await Governance.at(await ms.getLatestAddress(toHex('GV'))), - 2, - 0 - ); - }); - it('Add internal contract should revert if new contract address is null', async function() { - actionHash = encode1( - ['bytes2', 'address'], - [ - toHex('PS'), - ZERO_ADDRESS - ] - ); - await gvProp( - 9, - actionHash, - await MemberRoles.at(await ms.getLatestAddress(toHex('MR'))), - await Governance.at(await ms.getLatestAddress(toHex('GV'))), - 2, - 0 - ); - }); - it('Add internal contract should revert if new contract code is MS', async function() { - actionHash = encode1( - ['bytes2', 'address'], - [ - toHex('MS'), - gov.address - ] - ); - await gvProp( - 9, - actionHash, - await MemberRoles.at(await ms.getLatestAddress(toHex('MR'))), - await Governance.at(await ms.getLatestAddress(toHex('GV'))), - 2, - 0 - ); - }); - it('Upgrade contract implementation should revert if new address is null', async function() { - oldGv = await Governance.at(await ms.getLatestAddress(toHex('GV'))); - oldMR = await MemberRoles.at(await ms.getLatestAddress(toHex('MR'))); - gvProxy = await OwnedUpgradeabilityProxy.at( - await ms.getLatestAddress(toHex('GV')) - ); - let gvImplementationAdd = await gvProxy.implementation(); - oldPC = await ProposalCategory.at( - await ms.getLatestAddress(toHex('PC')) - ); - - let catId = 7; - - actionHash = encode1( - ['bytes2[]', 'address[]'], - [[toHex('GV')], [ZERO_ADDRESS]] - ); - - await gvProp( - catId, - actionHash, - await MemberRoles.at(await ms.getLatestAddress(toHex('MR'))), - await Governance.at(await ms.getLatestAddress(toHex('GV'))), - 2, - 0 - ); - assert.equal( - gvImplementationAdd, - await gvProxy.implementation() - ); - }); - it('Should revert if caller is not proxyOwner', async function() { - mas = await Master.new(); - mas = await OwnedUpgradeabilityProxy.new(mas.address); - mas = await Master.at(mas.address); - await assertRevert( - mas.initiateMaster([], mas.address, mas.address, mas.address, [mas.address, mas.address, mas.address], mas.address, {from: newOwner}) - ); - }); - it('Should revert if length of implementation array and contract array are not same', async function() { - await assertRevert( - mas.initiateMaster([], mas.address, mas.address, mas.address, [mas.address, mas.address, mas.address], mas.address) - ); - }); - it('Should revert if master already initiated', async function() { - await assertRevert( - ms.initiateMaster([], mas.address, mas.address, mas.address, [mas.address, mas.address, mas.address], mas.address) - ); }); }); diff --git a/test/09_multiplier.js b/test/09_multiplier.js deleted file mode 100644 index d4eda12bf..000000000 --- a/test/09_multiplier.js +++ /dev/null @@ -1,1000 +0,0 @@ -const { assert } = require("chai"); -const OwnedUpgradeabilityProxy = artifacts.require("OwnedUpgradeabilityProxy"); -const Market = artifacts.require("MockMarket"); -const Plotus = artifacts.require("MarketRegistry"); -const Master = artifacts.require("Master"); -const PlotusToken = artifacts.require("MockPLOT"); -const MarketConfig = artifacts.require("MockConfig"); -const MockUniswapRouter = artifacts.require("MockUniswapRouter"); -// const MockchainLinkBTC = artifacts.require("MockChainLinkAggregator"); -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; - -describe("1. Players are incentivized to stake DAO tokens to earn a multiplier on their positions", () => { - let predictionPointsBeforeUser1, predictionPointsBeforeUser2, predictionPointsBeforeUser3, predictionPointsBeforeUser4; - contract("Market", async function([user1, user2, user3, user4, user5, user6, user7, user8, user9, user10]) { - it("1.1 Position without locking PLOT tokens", async () => { - let masterInstance = await OwnedUpgradeabilityProxy.deployed(); - masterInstance = await Master.at(masterInstance.address); - let plotusToken = await PlotusToken.deployed(); - let tokenControllerAdd = await masterInstance.getLatestAddress(web3.utils.toHex("TC")); - let tokenController = await TokenController.at(tokenControllerAdd); - let plotusNewAddress = await masterInstance.getLatestAddress(web3.utils.toHex("PL")); - let plotusNewInstance = await Plotus.at(plotusNewAddress); - let marketConfig = await plotusNewInstance.marketUtility(); - marketConfig = await MarketConfig.at(marketConfig); - const openMarkets = await plotusNewInstance.getOpenMarkets(); - marketInstance = await Market.at(openMarkets["_openMarkets"][0]); - // await marketInstance.setMockPriceFlag(false); - await increaseTime(10001); - assert.ok(marketInstance); - await plotusToken.approve(tokenController.address, "10000000000000000000000"); - await plotusToken.transfer(user2, "2500000000000000000000"); - await plotusToken.transfer(user3, "2500000000000000000000"); - await plotusToken.transfer(user4, "2500000000000000000000"); - await plotusToken.transfer(user5, "2500000000000000000000"); - - await marketConfig.setOptionPrice(1, 9); - await marketConfig.setOptionPrice(2, 18); - await marketConfig.setOptionPrice(3, 27); - await plotusToken.approve(tokenController.address, "10000000000000000000000"); - await plotusToken.approve(tokenController.address, "10000000000000000000000", { from: user2 }); - - // await marketConfig.setAMLComplianceStatus(user1, true); - // await marketConfig.setKYCComplianceStatus(user1, true); - await marketInstance.placePrediction(plotusToken.address, "100000000000000000000", 2, 1, { - from: user1, - }); - // await marketConfig.setAMLComplianceStatus(user2, true); - // await marketConfig.setAMLComplianceStatus(user3, true); - // await marketConfig.setAMLComplianceStatus(user4, true); - // await marketConfig.setAMLComplianceStatus(user5, true); - - // await marketConfig.setKYCComplianceStatus(user1, true); - // await marketConfig.setKYCComplianceStatus(user2, true); - // await marketConfig.setKYCComplianceStatus(user3, true); - // await marketConfig.setKYCComplianceStatus(user4, true); - // await marketConfig.setKYCComplianceStatus(user5, true); - - await marketInstance.placePrediction(plotusToken.address, "400000000000000000000", 2, 2, { - from: user2, - }); - await plotusToken.approve(tokenController.address, "10000000000000000000000", { from: user3 }); - await marketInstance.placePrediction(plotusToken.address, "100000000000000000000", 1, 3, { - from: user3, - }); - await plotusToken.approve(tokenController.address, "10000000000000000000000", { from: user4 }); - await marketInstance.placePrediction(plotusToken.address, "100000000000000000000", 3, 4, { - from: user4, - }); - await plotusToken.approve(tokenController.address, "10000000000000000000000", { from: user5 }); - await marketInstance.placePrediction(plotusToken.address, "10000000000000000000", 3, 4, { - from: user5, - }); - predictionPointsBeforeUser1 = parseFloat(await marketInstance.getUserPredictionPoints(user1, 2)) / 1000; - predictionPointsBeforeUser2 = parseFloat(await marketInstance.getUserPredictionPoints(user2, 2)) / 1000; - predictionPointsBeforeUser3 = parseFloat(await marketInstance.getUserPredictionPoints(user3, 1)) / 1000; - predictionPointsBeforeUser4 = parseFloat(await marketInstance.getUserPredictionPoints(user4, 3)) / 1000; - predictionPointsBeforeUser5 = parseFloat(await marketInstance.getUserPredictionPoints(user5, 3)) / 1000; - // console.log( - // predictionPointsBeforeUser1, - // predictionPointsBeforeUser2, - // predictionPointsBeforeUser3, - // predictionPointsBeforeUser4, - // predictionPointsBeforeUser5 - // ); - assert.equal(predictionPointsBeforeUser1.toFixed(1), (55.5138941).toFixed(1)); - assert.equal(predictionPointsBeforeUser2.toFixed(1), (932.6334208).toFixed(1)); - assert.equal(predictionPointsBeforeUser3.toFixed(1), (366.391701).toFixed(1)); - assert.equal(predictionPointsBeforeUser4.toFixed(1), (170.2426086).toFixed(1)); - assert.equal(predictionPointsBeforeUser5.toFixed(1), (5.383543979).toFixed(1)); - }); - }); - contract("Market", async function([user1, user2, user3, user4, user5, user6, user7, user8, user9, user10]) { - it("1.2 Positions After locking PLOT tokens", async () => { - let masterInstance = await OwnedUpgradeabilityProxy.deployed(); - masterInstance = await Master.at(masterInstance.address); - let plotusToken = await PlotusToken.deployed(); - let tokenControllerAdd = await masterInstance.getLatestAddress(web3.utils.toHex("TC")); - let tokenController = await TokenController.at(tokenControllerAdd); - let plotusNewAddress = await masterInstance.getLatestAddress(web3.utils.toHex("PL")); - let plotusNewInstance = await Plotus.at(plotusNewAddress); - let marketConfig = await plotusNewInstance.marketUtility(); - marketConfig = await MarketConfig.at(marketConfig); - const openMarkets = await plotusNewInstance.getOpenMarkets(); - marketInstance = await Market.at(openMarkets["_openMarkets"][0]); - // await marketInstance.setMockPriceFlag(false); - await increaseTime(10001); - assert.ok(marketInstance); - await plotusToken.approve(tokenController.address, "10000000000000000000000", { from: user1 }); - await tokenController.lock("0x534d", "1100000000000000000000", 86400 * 30, { from: user1 }); - await plotusToken.transfer(user2, "2500000000000000000000"); - await plotusToken.approve(tokenController.address, "10000000000000000000000", { from: user2 }); - await tokenController.lock("0x534d", "1600000000000000000000", 86400 * 30, { from: user2 }); - await plotusToken.transfer(user3, "2500000000000000000000"); - await plotusToken.approve(tokenController.address, "10000000000000000000000", { from: user3 }); - await tokenController.lock("0x534d", "1100000000000000000000", 86400 * 30, { from: user3 }); - await plotusToken.transfer(user4, "2500000000000000000000"); - await plotusToken.approve(tokenController.address, "10000000000000000000000", { from: user4 }); - await tokenController.lock("0x534d", "1100000000000000000000", 86400 * 30, { from: user4 }); - await plotusToken.transfer(user5, "2500000000000000000000"); - await plotusToken.approve(tokenController.address, "10000000000000000000000", { from: user5 }); - await tokenController.lock("0x534d", "1100", 86400 * 30, { from: user5 }); - - await marketConfig.setOptionPrice(1, 9); - await marketConfig.setOptionPrice(2, 18); - await marketConfig.setOptionPrice(3, 27); - - await plotusToken.approve(tokenController.address, "10000000000000000000000"); - await marketInstance.placePrediction(plotusToken.address, "100000000000000000000", 2, 1, { - from: user1, - }); - await plotusToken.approve(tokenController.address, "10000000000000000000000", { from: user2 }); - await marketInstance.placePrediction(plotusToken.address, "400000000000000000000", 2, 2, { - from: user2, - }); - await plotusToken.approve(tokenController.address, "10000000000000000000000", { from: user3 }); - await marketInstance.placePrediction(plotusToken.address, "100000000000000000000", 1, 3, { - from: user3, - }); - await plotusToken.approve(tokenController.address, "10000000000000000000000", { from: user4 }); - await marketInstance.placePrediction(plotusToken.address, "100000000000000000000", 3, 4, { - from: user4, - }); - await plotusToken.approve(tokenController.address, "10000000000000000000000", { from: user5 }); - await marketInstance.placePrediction(plotusToken.address, "10000000000000000000", 3, 4, { - from: user5, - }); - let predictionPointsUser1 = parseFloat(await marketInstance.getUserPredictionPoints(user1, 2)) / 1000; - let predictionPointsUser2 = parseFloat(await marketInstance.getUserPredictionPoints(user2, 2)) / 1000; - let predictionPointsUser3 = parseFloat(await marketInstance.getUserPredictionPoints(user3, 1)) / 1000; - let predictionPointsUser4 = parseFloat(await marketInstance.getUserPredictionPoints(user4, 3)) / 1000; - let predictionPointsUser5 = parseFloat(await marketInstance.getUserPredictionPoints(user5, 3)) / 1000; - - //console.log(predictionPointsUser1, predictionPointsUser2, predictionPointsUser3, predictionPointsUser4, predictionPointsUser5); - assert.equal(predictionPointsUser1.toFixed(1), (116.5791776).toFixed(1)); - assert.equal(predictionPointsUser2.toFixed(1), (1305.686789).toFixed(1)); - assert.equal(predictionPointsUser3.toFixed(1), (769.4225722).toFixed(1)); - assert.equal(predictionPointsUser4.toFixed(1), (357.509478).toFixed(1)); - assert.equal(predictionPointsUser5.toFixed(1), (5.383543979).toFixed(1)); - }); - }); -}); - -describe("2. Place prediction with ETH and check multiplier ", () => { - let predictionPointsUser1, predictionPointsUser1_2, predictionPointsUser2, predictionPointsUser3, predictionPointsUser4; - contract("Market", async function([user1, user2, user3, user4, user5]) { - let masterInstance, - plotusToken, - marketConfig, - MockUniswapRouterInstance, - tokenControllerAdd, - tokenController, - plotusNewAddress, - plotusNewInstance; - 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")); - MockUniswapRouterInstance = await MockUniswapRouter.deployed(); - plotusNewInstance = await Plotus.at(plotusNewAddress); - marketConfig = await plotusNewInstance.marketUtility(); - marketConfig = await MarketConfig.at(marketConfig); - - openMarkets = await plotusNewInstance.getOpenMarkets(); - marketInstance = await Market.at(openMarkets["_openMarkets"][0]); - assert.ok(marketInstance); - await increaseTime(10001); - - await MockUniswapRouterInstance.setPrice("1000000000000000"); - await marketConfig.setPrice("1000000000000000"); - - await marketConfig.setOptionPrice(1, 9); - await marketConfig.setOptionPrice(2, 18); - await marketConfig.setOptionPrice(3, 27); - }); - - it("2.1", async () => { - await plotusToken.transfer(user2, web3.utils.toWei("1000")); - await plotusToken.transfer(user3, web3.utils.toWei("10000")); - await plotusToken.transfer(user4, web3.utils.toWei("20000")); - - await marketInstance.placePrediction("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", web3.utils.toWei("10"), 1, 4, { - from: user1, - value: web3.utils.toWei("10"), - }); - await marketInstance.placePrediction("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", web3.utils.toWei("10"), 2, 4, { - from: user1, - value: web3.utils.toWei("10"), - }); - await marketInstance.placePrediction("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", web3.utils.toWei("10"), 2, 5, { - from: user2, - value: web3.utils.toWei("10"), - }); - await marketInstance.placePrediction("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", web3.utils.toWei("10"), 3, 5, { - from: user3, - value: web3.utils.toWei("10"), - }); - await marketInstance.placePrediction("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", web3.utils.toWei("10"), 1, 5, { - from: user4, - value: web3.utils.toWei("10"), - }); - await marketInstance.placePrediction("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", web3.utils.toWei("0.2"), 2, 2, { - from: user5, - value: web3.utils.toWei("0.2"), - }); - - predictionPointsUser1 = parseFloat(await marketInstance.getUserPredictionPoints(user1, 1)) / 1000; - predictionPointsUser1_2 = parseFloat(await marketInstance.getUserPredictionPoints(user1, 2)) / 1000; - predictionPointsUser2 = parseFloat(await marketInstance.getUserPredictionPoints(user2, 2)) / 1000; - predictionPointsUser3 = parseFloat(await marketInstance.getUserPredictionPoints(user3, 3)) / 1000; - predictionPointsUser4 = parseFloat(await marketInstance.getUserPredictionPoints(user4, 1)) / 1000; - predictionPointsUser5 = parseFloat(await marketInstance.getUserPredictionPoints(user5, 2)) / 1000; - // console.log( - // predictionPointsUser1, - // predictionPointsUser1_2, - // predictionPointsUser2, - // predictionPointsUser3, - // predictionPointsUser4, - // predictionPointsUser5 - // ); - - assert.equal(Math.floor(predictionPointsUser1), Math.floor(16138.51442)); - assert.equal(Math.floor(predictionPointsUser1_2), Math.floor(8069.257209)); - assert.equal(Math.floor(predictionPointsUser2), Math.floor(10525.1181)); - assert.equal(Math.floor(predictionPointsUser3), Math.floor(7016.745399)); - assert.equal(Math.floor(predictionPointsUser4), Math.floor(21050.2362)); - assert.equal(Math.floor(predictionPointsUser5), Math.floor(10.41933533)); - }); - }); - contract("Market", async function([user1, user2, user3, user4, user5]) { - let masterInstance, - plotusToken, - marketConfig, - MockUniswapRouterInstance, - tokenControllerAdd, - tokenController, - plotusNewAddress, - plotusNewInstance; - 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")); - MockUniswapRouterInstance = await MockUniswapRouter.deployed(); - plotusNewInstance = await Plotus.at(plotusNewAddress); - marketConfig = await plotusNewInstance.marketUtility(); - marketConfig = await MarketConfig.at(marketConfig); - - openMarkets = await plotusNewInstance.getOpenMarkets(); - marketInstance = await Market.at(openMarkets["_openMarkets"][0]); - assert.ok(marketInstance); - await increaseTime(10001); - - await MockUniswapRouterInstance.setPrice("1000000000000000"); - await marketConfig.setPrice("1000000000000000"); - - await marketConfig.setOptionPrice(1, 9); - await marketConfig.setOptionPrice(2, 18); - await marketConfig.setOptionPrice(3, 27); - }); - it("2.2", async () => { - await plotusToken.approve(tokenController.address, "1000000000000000000000000", { from: user1 }); - await tokenController.lock("0x534d", web3.utils.toWei("110000"), 86400 * 30, { from: user1 }); - - await plotusToken.transfer(user2, web3.utils.toWei("1000")); - await plotusToken.approve(tokenController.address, "1000000000000000000000000", { from: user2 }); - await tokenController.lock("0x534d", web3.utils.toWei("1000"), 86400 * 30, { from: user2 }); - - await plotusToken.transfer(user3, web3.utils.toWei("100000")); - await plotusToken.approve(tokenController.address, "1000000000000000000000000", { from: user3 }); - await tokenController.lock("0x534d", web3.utils.toWei("100000"), 86400 * 30, { from: user3 }); - - await plotusToken.transfer(user4, web3.utils.toWei("200000")); - await plotusToken.approve(tokenController.address, "1000000000000000000000000", { from: user4 }); - await tokenController.lock("0x534d", web3.utils.toWei("200000"), 86400 * 30, { from: user4 }); - - await plotusToken.transfer(user5, web3.utils.toWei("11000")); - await plotusToken.approve(tokenController.address, "1000000000000000000000000", { from: user5 }); - await tokenController.lock("0x534d", web3.utils.toWei("11000"), 86400 * 30, { from: user5 }); - - await marketInstance.placePrediction("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", web3.utils.toWei("10"), 1, 4, { - from: user1, - value: web3.utils.toWei("10"), - }); - await marketInstance.placePrediction("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", web3.utils.toWei("10"), 2, 4, { - from: user1, - value: web3.utils.toWei("10"), - }); - await marketInstance.placePrediction("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", web3.utils.toWei("10"), 2, 5, { - from: user2, - value: web3.utils.toWei("10"), - }); - await marketInstance.placePrediction("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", web3.utils.toWei("10"), 3, 5, { - from: user3, - value: web3.utils.toWei("10"), - }); - await marketInstance.placePrediction("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", web3.utils.toWei("10"), 1, 5, { - from: user4, - value: web3.utils.toWei("10"), - }); - await marketInstance.placePrediction("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", web3.utils.toWei("0.2"), 2, 2, { - from: user5, - value: web3.utils.toWei("0.2"), - }); - - let predictionPointsWithLockUser1 = parseFloat(await marketInstance.getUserPredictionPoints(user1, 1)) / 1000; - let predictionPointsWithLockUser1_2 = parseFloat(await marketInstance.getUserPredictionPoints(user1, 2)) / 1000; - let predictionPointsWithLockUser2 = parseFloat(await marketInstance.getUserPredictionPoints(user2, 2)) / 1000; - let predictionPointsWithLockUser3 = parseFloat(await marketInstance.getUserPredictionPoints(user3, 3)) / 1000; - let predictionPointsWithLockUser4 = parseFloat(await marketInstance.getUserPredictionPoints(user4, 1)) / 1000; - let predictionPointsWithLockUser5 = parseFloat(await marketInstance.getUserPredictionPoints(user5, 2)) / 1000; - - // console.log( - // predictionPointsWithLockUser1, - // predictionPointsWithLockUser1_2, - // predictionPointsWithLockUser2, - // predictionPointsWithLockUser3, - // predictionPointsWithLockUser4, - // predictionPointsWithLockUser5 - // ); - - assert.equal(Math.floor(predictionPointsWithLockUser1), Math.floor(33890.707)); - assert.equal(Math.floor(predictionPointsWithLockUser1_2), Math.floor(8069.216)); - assert.equal(Math.floor(predictionPointsWithLockUser2), Math.floor(10525.064)); - assert.equal(Math.floor(predictionPointsWithLockUser3), Math.floor(14033.418)); - assert.equal(Math.floor(predictionPointsWithLockUser4), Math.floor(63150.384)); - assert.equal(Math.floor(predictionPointsWithLockUser5), Math.floor(10.41933533)); - }); - }); -}); - -describe("3. Multiple Option predictions", () => { - contract("Market", async function([user1, user2, user3, user4, user5]) { - let masterInstance, marketConfig, plotusToken, tokenControllerAdd, tokenController, plotusNewAddress, plotusNewInstance; - 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")); - plotusNewInstance = await Plotus.at(plotusNewAddress); - marketConfig = await plotusNewInstance.marketUtility(); - marketConfig = await MarketConfig.at(marketConfig); - openMarkets = await plotusNewInstance.getOpenMarkets(); - marketInstance = await Market.at(openMarkets["_openMarkets"][0]); - assert.ok(marketInstance); - await increaseTime(10001); - // Transfer Tokens - await plotusToken.transfer(user2, web3.utils.toWei("5000")); - await plotusToken.transfer(user3, web3.utils.toWei("5000")); - - await marketConfig.setOptionPrice(1, 9); - await marketConfig.setOptionPrice(2, 18); - await marketConfig.setOptionPrice(3, 27); - - await plotusToken.approve(tokenController.address, web3.utils.toWei("500")); - await plotusToken.approve(tokenController.address, web3.utils.toWei("500"), { from: user2 }); - await plotusToken.approve(tokenController.address, web3.utils.toWei("500"), { from: user3 }); - }); - - it("3.1. Scenario 1 ", async () => { - const oldPlotusTokenBalance = parseFloat(web3.utils.fromWei(await plotusToken.balanceOf(plotusNewInstance.address))); - - await marketInstance.placePrediction(plotusToken.address, web3.utils.toWei("100"), 1, 1, { from: user1 }); - await marketInstance.placePrediction(plotusToken.address, web3.utils.toWei("400"), 1, 2, { from: user1 }); - await marketInstance.placePrediction(plotusToken.address, web3.utils.toWei("400"), 1, 2, { from: user2 }); - await marketInstance.placePrediction(plotusToken.address, web3.utils.toWei("400"), 2, 2, { from: user3 }); - - const predictionPointsUser1 = parseFloat(await marketInstance.getUserPredictionPoints(user1, 1)); - const predictionPointsUser2 = parseFloat(await marketInstance.getUserPredictionPoints(user2, 1)); - const predictionPointsUser3 = parseFloat(await marketInstance.getUserPredictionPoints(user3, 2)); - - await increaseTime(36001); - await marketInstance.calculatePredictionResult(1); - await increaseTime(36001); - - let returnUser1 = parseFloat((await marketInstance.getReturn(user1))[0][0]); - let returnUser2 = parseFloat((await marketInstance.getReturn(user2))[0][0]); - let returnUser3 = parseFloat((await marketInstance.getReturn(user3))[0][0]); - returnUser1 = web3.utils.fromWei(returnUser1.toString()); - returnUser2 = web3.utils.fromWei(returnUser2.toString()); - returnUser3 = web3.utils.fromWei(returnUser3.toString()); - - //console.log("(predictionPointsUser1 / 10000).toFixed(1)", predictionPointsUser1 ); - //console.log("(predictionPointsUser2 / 10000).toFixed(1)", predictionPointsUser2 ); - //console.log("(predictionPointsUser3 / 10000).toFixed(1)", predictionPointsUser3 ); - //console.log("parseFloat(returnUser1).toFixed(3)", parseFloat(returnUser1)); - //console.log("parseFloat(returnUser2).toFixed(3)", parseFloat(returnUser2)); - //console.log("parseFloat(returnUser3).toFixed(3)", parseFloat(returnUser3)); - - assert.equal((predictionPointsUser1 / 10000).toFixed(1), (197.629463).toFixed(1)); - assert.equal((predictionPointsUser2 / 10000).toFixed(1), (186.5266842).toFixed(1)); - assert.equal((predictionPointsUser3 / 10000).toFixed(1), (93.26334208).toFixed(1)); - assert.equal(parseFloat(returnUser1).toFixed(), (581.9592486).toFixed()); - assert.equal(parseFloat(returnUser2).toFixed(), (477.3907514).toFixed()); - assert.equal(parseFloat(returnUser3).toFixed(), (240).toFixed()); - - const newPlotusTokenBalance = parseFloat(web3.utils.fromWei(await plotusToken.balanceOf(plotusNewInstance.address))); - //console.log("(newPlotusTokenBalance - oldPlotusTokenBalance).toFixed(2)", (newPlotusTokenBalance - oldPlotusTokenBalance).toFixed(2)) - assert.equal((newPlotusTokenBalance - oldPlotusTokenBalance).toFixed(2), (0.65).toFixed(2)); - }); - }); - contract("Market", async function([user1, user2, user3, user4, user5]) { - let masterInstance, marketConfig, plotusToken, tokenControllerAdd, tokenController, plotusNewAddress, plotusNewInstance; - 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")); - plotusNewInstance = await Plotus.at(plotusNewAddress); - marketConfig = await plotusNewInstance.marketUtility(); - marketConfig = await MarketConfig.at(marketConfig); - openMarkets = await plotusNewInstance.getOpenMarkets(); - marketInstance = await Market.at(openMarkets["_openMarkets"][0]); - assert.ok(marketInstance); - await increaseTime(10001); - // Transfer Tokens - await plotusToken.transfer(user2, web3.utils.toWei("5000")); - await plotusToken.transfer(user3, web3.utils.toWei("5000")); - - await marketConfig.setOptionPrice(1, 9); - await marketConfig.setOptionPrice(2, 18); - await marketConfig.setOptionPrice(3, 27); - - await plotusToken.approve(tokenController.address, web3.utils.toWei("500")); - await plotusToken.approve(tokenController.address, web3.utils.toWei("500"), { from: user2 }); - await plotusToken.approve(tokenController.address, web3.utils.toWei("500"), { from: user3 }); - }); - - it("3.2. Scenario 2", async () => { - const oldPlotusTokenBalance = parseFloat(web3.utils.fromWei(await plotusToken.balanceOf(plotusNewInstance.address))); - - await marketInstance.placePrediction(plotusToken.address, web3.utils.toWei("100"), 2, 1, { from: user1 }); - await marketInstance.placePrediction(plotusToken.address, web3.utils.toWei("400"), 2, 2, { from: user1 }); - await marketInstance.placePrediction(plotusToken.address, web3.utils.toWei("400"), 1, 2, { from: user2 }); - await marketInstance.placePrediction(plotusToken.address, web3.utils.toWei("400"), 2, 2, { from: user3 }); - - const predictionPointsUser1 = parseFloat(await marketInstance.getUserPredictionPoints(user1, 2)); - const predictionPointsUser2 = parseFloat(await marketInstance.getUserPredictionPoints(user2, 1)); - const predictionPointsUser3 = parseFloat(await marketInstance.getUserPredictionPoints(user3, 2)); - - await increaseTime(36001); - await marketInstance.calculatePredictionResult(1); - await increaseTime(36001); - - let returnUser1 = parseFloat((await marketInstance.getReturn(user1))[0][0]); - let returnUser2 = parseFloat((await marketInstance.getReturn(user2))[0][0]); - let returnUser3 = parseFloat((await marketInstance.getReturn(user3))[0][0]); - returnUser1 = web3.utils.fromWei(returnUser1.toString()); - returnUser2 = web3.utils.fromWei(returnUser2.toString()); - returnUser3 = web3.utils.fromWei(returnUser3.toString()); - - //console.log("(predictionPointsUser1 / 10000).toFixed(1)", predictionPointsUser1 ); - //console.log("(predictionPointsUser2 / 10000).toFixed(1)", predictionPointsUser2 ); - //console.log("(predictionPointsUser3 / 10000).toFixed(1)", predictionPointsUser3 ); - //console.log("parseFloat(returnUser1).toFixed(3)", parseFloat(returnUser1)); - //console.log("parseFloat(returnUser2).toFixed(3)", parseFloat(returnUser2)); - //console.log("parseFloat(returnUser3).toFixed(3)", parseFloat(returnUser3)); - - assert.equal((predictionPointsUser1 / 10000).toFixed(1), (98.81473149).toFixed(1)); - assert.equal((predictionPointsUser2 / 10000).toFixed(1), (186.5266842).toFixed(1)); - assert.equal((predictionPointsUser3 / 10000).toFixed(1), (93.26334208).toFixed(1)); - assert.equal(parseFloat(returnUser1).toFixed(3), (319.84).toFixed(3)); - assert.equal(parseFloat(returnUser2).toFixed(3), (739.63).toFixed(3)); - assert.equal(parseFloat(returnUser3).toFixed(3), (239.88).toFixed(3)); - - const newPlotusTokenBalance = parseFloat(web3.utils.fromWei(await plotusToken.balanceOf(plotusNewInstance.address))); - assert.equal((newPlotusTokenBalance - oldPlotusTokenBalance).toFixed(2), "0.65"); - }); - }); - contract("Market", async function([user1, user2, user3, user4, user5]) { - let masterInstance, marketConfig, plotusToken, tokenControllerAdd, tokenController, plotusNewAddress, plotusNewInstance; - 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")); - plotusNewInstance = await Plotus.at(plotusNewAddress); - marketConfig = await plotusNewInstance.marketUtility(); - marketConfig = await MarketConfig.at(marketConfig); - openMarkets = await plotusNewInstance.getOpenMarkets(); - marketInstance = await Market.at(openMarkets["_openMarkets"][0]); - assert.ok(marketInstance); - await increaseTime(10001); - // Transfer Tokens - await plotusToken.transfer(user2, web3.utils.toWei("5000")); - await plotusToken.transfer(user3, web3.utils.toWei("5000")); - - await marketConfig.setOptionPrice(1, 9); - await marketConfig.setOptionPrice(2, 18); - await marketConfig.setOptionPrice(3, 27); - - await plotusToken.approve(tokenController.address, web3.utils.toWei("500")); - await plotusToken.approve(tokenController.address, web3.utils.toWei("500"), { from: user2 }); - await plotusToken.approve(tokenController.address, web3.utils.toWei("500"), { from: user3 }); - }); - - it("3.3. Scenario 3 ", async () => { - const oldPlotusTokenBalance = parseFloat(web3.utils.fromWei(await plotusToken.balanceOf(plotusNewInstance.address))); - - await marketInstance.placePrediction(plotusToken.address, web3.utils.toWei("100"), 1, 1, { from: user1 }); - await marketInstance.placePrediction(plotusToken.address, web3.utils.toWei("400"), 2, 2, { from: user1 }); - await marketInstance.placePrediction(plotusToken.address, web3.utils.toWei("400"), 1, 2, { from: user2 }); - await marketInstance.placePrediction(plotusToken.address, web3.utils.toWei("400"), 2, 2, { from: user3 }); - - const predictionPointsUser1 = parseFloat(await marketInstance.getUserPredictionPoints(user1, 1)); - const predictionPointsUser1_2 = parseFloat(await marketInstance.getUserPredictionPoints(user1, 2)); - const predictionPointsUser2 = parseFloat(await marketInstance.getUserPredictionPoints(user2, 1)); - const predictionPointsUser3 = parseFloat(await marketInstance.getUserPredictionPoints(user3, 2)); - - await increaseTime(36001); - await marketInstance.calculatePredictionResult(1); - await increaseTime(36001); - - let returnUser1 = parseFloat((await marketInstance.getReturn(user1))[0][0]); - let returnUser2 = parseFloat((await marketInstance.getReturn(user2))[0][0]); - let returnUser3 = parseFloat((await marketInstance.getReturn(user3))[0][0]); - returnUser1 = web3.utils.fromWei(returnUser1.toString()); - returnUser2 = web3.utils.fromWei(returnUser2.toString()); - returnUser3 = web3.utils.fromWei(returnUser3.toString()); - - //console.log("(predictionPointsUser1 / 10000).toFixed(1)", predictionPointsUser1 ); - //console.log("(predictionPointsUser2 / 10000).toFixed(1)", predictionPointsUser2 ); - //console.log("(predictionPointsUser3 / 10000).toFixed(1)", predictionPointsUser3 ); - //console.log("parseFloat(returnUser1).toFixed(3)", parseFloat(returnUser1)); - //console.log("parseFloat(returnUser2).toFixed(3)", parseFloat(returnUser2)); - //console.log("parseFloat(returnUser3).toFixed(3)", parseFloat(returnUser3)); - - assert.equal((predictionPointsUser1 / 10000).toFixed(1), (11.10277882).toFixed(1)); - assert.equal((predictionPointsUser1_2 / 10000).toFixed(1), (93.26334208).toFixed(1)); - assert.equal((predictionPointsUser2 / 10000).toFixed(1), (186.5266842).toFixed(1)); - assert.equal((predictionPointsUser3 / 10000).toFixed(1), (93.26334208).toFixed(1)); - assert.equal(parseFloat(returnUser1).toFixed(2), (357.7985393).toFixed(2)); - assert.equal(parseFloat(returnUser2).toFixed(2), (701.6714607).toFixed(2)); - assert.equal(parseFloat(returnUser3).toFixed(2), (239.88).toFixed(2)); - - const newPlotusTokenBalance = parseFloat(web3.utils.fromWei(await plotusToken.balanceOf(plotusNewInstance.address))); - assert.equal((newPlotusTokenBalance - oldPlotusTokenBalance).toFixed(2), "0.65"); - }); - }); - contract("Market", async function([user1, user2, user3, user4, user5]) { - let masterInstance, marketConfig, plotusToken, tokenControllerAdd, tokenController, plotusNewAddress, plotusNewInstance; - 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")); - plotusNewInstance = await Plotus.at(plotusNewAddress); - marketConfig = await plotusNewInstance.marketUtility(); - marketConfig = await MarketConfig.at(marketConfig); - openMarkets = await plotusNewInstance.getOpenMarkets(); - marketInstance = await Market.at(openMarkets["_openMarkets"][0]); - assert.ok(marketInstance); - await increaseTime(10001); - // Transfer Tokens - await plotusToken.transfer(user2, web3.utils.toWei("5000")); - await plotusToken.transfer(user3, web3.utils.toWei("5000")); - - await marketConfig.setOptionPrice(1, 9); - await marketConfig.setOptionPrice(2, 18); - await marketConfig.setOptionPrice(3, 27); - - await plotusToken.approve(tokenController.address, web3.utils.toWei("500")); - await plotusToken.approve(tokenController.address, web3.utils.toWei("500"), { from: user2 }); - await plotusToken.approve(tokenController.address, web3.utils.toWei("500"), { from: user3 }); - }); - - it("3.4. Scenario 4", async () => { - const oldPlotusTokenBalance = parseFloat(web3.utils.fromWei(await plotusToken.balanceOf(plotusNewInstance.address))); - const oldPlotusETHBalance = parseFloat(await web3.eth.getBalance(plotusNewInstance.address)); - assert.equal(oldPlotusETHBalance, 0); - - await marketInstance.placePrediction("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", web3.utils.toWei("4"), 1, 1, { - from: user1, - value: web3.utils.toWei("4"), - }); - await marketInstance.placePrediction(plotusToken.address, web3.utils.toWei("400"), 1, 2, { from: user1 }); - await marketInstance.placePrediction(plotusToken.address, web3.utils.toWei("400"), 3, 2, { from: user2 }); - await marketInstance.placePrediction(plotusToken.address, web3.utils.toWei("400"), 2, 2, { from: user3 }); - - const predictionPointsUser1 = parseFloat(await marketInstance.getUserPredictionPoints(user1, 1)); - const predictionPointsUser2 = parseFloat(await marketInstance.getUserPredictionPoints(user2, 3)); - const predictionPointsUser3 = parseFloat(await marketInstance.getUserPredictionPoints(user3, 2)); - - assert.equal((predictionPointsUser1 / 10000).toFixed(1), (275.2822731).toFixed(1)); - assert.equal((predictionPointsUser2 / 10000).toFixed(1), (62.17556139).toFixed(1)); - assert.equal((predictionPointsUser3 / 10000).toFixed(1), (93.26334208).toFixed(1)); - - let oldOwnerBalance1 = parseFloat(web3.utils.fromWei((await plotusToken.balanceOf(user1)).toString())); - let oldOwnerBalance2 = parseFloat(web3.utils.fromWei((await plotusToken.balanceOf(user2)).toString())); - let oldOwnerBalance3 = parseFloat(web3.utils.fromWei((await plotusToken.balanceOf(user3)).toString())); - - await increaseTime(360001); - await marketInstance.calculatePredictionResult(1); - await increaseTime(360001); - await marketInstance.claimReturn(user1); - await marketInstance.claimReturn(user2); - await marketInstance.claimReturn(user3); - - let newOwnerBalance1 = parseFloat(web3.utils.fromWei((await plotusToken.balanceOf(user1)).toString())); - let newOwnerBalance2 = parseFloat(web3.utils.fromWei((await plotusToken.balanceOf(user2)).toString())); - let newOwnerBalance3 = parseFloat(web3.utils.fromWei((await plotusToken.balanceOf(user3)).toString())); - - //console.log("(newOwnerBalance1 - oldOwnerBalance1).toFixed(2)", newOwnerBalance1 - oldOwnerBalance1); - //console.log("(newOwnerBalance2 - oldOwnerBalance2).toFixed(2)", newOwnerBalance2 - oldOwnerBalance2); - //console.log("(newOwnerBalance3 - oldOwnerBalance3).toFixed(2)", newOwnerBalance3 - oldOwnerBalance3); - - assert.equal((newOwnerBalance1 - oldOwnerBalance1).toFixed(2), (719.64).toFixed(2)); - assert.equal((newOwnerBalance2 - oldOwnerBalance2).toFixed(2), (239.88).toFixed(2)); - assert.equal((newOwnerBalance3 - oldOwnerBalance3).toFixed(2), (239.88).toFixed(2)); - - // let returnTokenIncentiveUser1 = parseFloat(web3.utils.fromWei((await marketInstance.getReturn(user1)).incentive[0].toString())); - // let returnTokenIncentiveUser2 = parseFloat(web3.utils.fromWei((await marketInstance.getReturn(user2)).incentive[0].toString())); - // let returnTokenIncentiveUser3 = parseFloat(web3.utils.fromWei((await marketInstance.getReturn(user3)).incentive[0].toString())); - - let returnTokenUser1 = parseFloat((await marketInstance.getReturn(user1))[0][0]); - let returnTokenUser2 = parseFloat((await marketInstance.getReturn(user2))[0][0]); - let returnTokenUser3 = parseFloat((await marketInstance.getReturn(user3))[0][0]); - let returnETHUser1 = parseFloat((await marketInstance.getReturn(user1))[0][1]); - let returnETHUser2 = parseFloat((await marketInstance.getReturn(user2))[0][1]); - let returnETHUser3 = parseFloat((await marketInstance.getReturn(user3))[0][1]); - returnTokenUser1 = web3.utils.fromWei(returnTokenUser1.toString()); - returnTokenUser2 = web3.utils.fromWei(returnTokenUser2.toString()); - returnTokenUser3 = web3.utils.fromWei(returnTokenUser3.toString()); - returnETHUser1 = web3.utils.fromWei(returnETHUser1.toString()); - returnETHUser2 = web3.utils.fromWei(returnETHUser2.toString()); - returnETHUser3 = web3.utils.fromWei(returnETHUser3.toString()); - - //console.log("(parseFloat(returnTokenUser1) + returnTokenIncentiveUser1).toFixed(2)", parseFloat(returnTokenUser1)) - //console.log("(parseFloat(returnTokenUser2) + returnTokenIncentiveUser2).toFixed(2)", parseFloat(returnTokenUser2)) - //console.log("(parseFloat(returnTokenUser3) + returnTokenIncentiveUser3).toFixed(2)", parseFloat(returnTokenUser3)) - //console.log("parseFloat(returnETHUser1).toFixed(2)", parseFloat(returnETHUser1)) - //console.log("parseFloat(returnETHUser2).toFixed(2)", parseFloat(returnETHUser2)) - //console.log("parseFloat(returnETHUser3).toFixed(2)", parseFloat(returnETHUser3)) - - assert.equal(parseFloat(returnTokenUser1).toFixed(2), (719.64).toFixed(2)); - assert.equal(parseFloat(returnTokenUser2).toFixed(2), (239.88).toFixed(2)); - assert.equal(parseFloat(returnTokenUser3).toFixed(2), (239.88).toFixed(2)); - assert.equal(parseFloat(returnETHUser1).toFixed(2), (3.996).toFixed(2)); - assert.equal(parseFloat(returnETHUser2).toFixed(2), (0).toFixed(2)); - assert.equal(parseFloat(returnETHUser3).toFixed(2), (0).toFixed(2)); - - const newPlotusTokenBalance = parseFloat(web3.utils.fromWei(await plotusToken.balanceOf(plotusNewInstance.address))); - const newPlotusETHBalance = parseFloat(web3.utils.fromWei(await web3.eth.getBalance(plotusNewInstance.address))); - //console.log((newPlotusTokenBalance - oldPlotusTokenBalance)); - assert.equal((newPlotusTokenBalance - oldPlotusTokenBalance).toFixed(2), "0.60"); - //console.log(newPlotusETHBalance); - assert.equal(newPlotusETHBalance, 0.004); - //console.log(parseFloat(await plotusToken.balanceOf(marketInstance.address))); - //console.log(parseFloat(web3.utils.fromWei(await web3.eth.getBalance(marketInstance.address)))); - - }); - }); - contract("Market", async function([user1, user2, user3, user4, user5]) { - let masterInstance, marketConfig, plotusToken, tokenControllerAdd, tokenController, plotusNewAddress, plotusNewInstance; - 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")); - plotusNewInstance = await Plotus.at(plotusNewAddress); - marketConfig = await plotusNewInstance.marketUtility(); - marketConfig = await MarketConfig.at(marketConfig); - openMarkets = await plotusNewInstance.getOpenMarkets(); - marketInstance = await Market.at(openMarkets["_openMarkets"][0]); - assert.ok(marketInstance); - await increaseTime(10001); - // Transfer Tokens - await plotusToken.transfer(user2, web3.utils.toWei("5000")); - await plotusToken.transfer(user3, web3.utils.toWei("5000")); - - await marketConfig.setOptionPrice(1, 9); - await marketConfig.setOptionPrice(2, 18); - await marketConfig.setOptionPrice(3, 27); - - await plotusToken.approve(tokenController.address, web3.utils.toWei("500")); - await plotusToken.approve(tokenController.address, web3.utils.toWei("500"), { from: user2 }); - await plotusToken.approve(tokenController.address, web3.utils.toWei("500"), { from: user3 }); - }); - - it("3.5. Scenario 5", async () => { - const oldPlotusTokenBalance = parseFloat(web3.utils.fromWei(await plotusToken.balanceOf(plotusNewInstance.address))); - - await marketInstance.placePrediction(plotusToken.address, web3.utils.toWei("100"), 2, 1, { from: user1 }); - await marketInstance.placePrediction("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", web3.utils.toWei("4"), 2, 2, { - from: user1, - value: web3.utils.toWei("4"), - }); - await marketInstance.placePrediction(plotusToken.address, web3.utils.toWei("400"), 3, 2, { from: user2 }); - await marketInstance.placePrediction(plotusToken.address, web3.utils.toWei("400"), 1, 2, { from: user3 }); - - const predictionPointsUser1 = parseFloat(await marketInstance.getUserPredictionPoints(user1, 2)); - const predictionPointsUser2 = parseFloat(await marketInstance.getUserPredictionPoints(user2, 3)); - const predictionPointsUser3 = parseFloat(await marketInstance.getUserPredictionPoints(user3, 1)); - - assert.equal((predictionPointsUser1 / 10000).toFixed(1), (98.74475775).toFixed(1)); - assert.equal((predictionPointsUser2 / 10000).toFixed(1), (62.17556139).toFixed(1)); - assert.equal(parseInt(predictionPointsUser3 / 10000), parseInt(186.3867367)); - - let oldOwnerBalance1 = parseFloat(web3.utils.fromWei((await plotusToken.balanceOf(user1)).toString())); - let oldOwnerBalance2 = parseFloat(web3.utils.fromWei((await plotusToken.balanceOf(user2)).toString())); - let oldOwnerBalance3 = parseFloat(web3.utils.fromWei((await plotusToken.balanceOf(user3)).toString())); - - await increaseTime(360001); - await marketInstance.calculatePredictionResult(1); - await increaseTime(360001); - await marketInstance.claimReturn(user1); - await marketInstance.claimReturn(user2); - await marketInstance.claimReturn(user3); - - let newOwnerBalance1 = parseFloat(web3.utils.fromWei((await plotusToken.balanceOf(user1)).toString())); - let newOwnerBalance2 = parseFloat(web3.utils.fromWei((await plotusToken.balanceOf(user2)).toString())); - let newOwnerBalance3 = parseFloat(web3.utils.fromWei((await plotusToken.balanceOf(user3)).toString())); - - assert.equal((newOwnerBalance1 - oldOwnerBalance1).toFixed(2), (79.96).toFixed(2)); - assert.equal((newOwnerBalance2 - oldOwnerBalance2).toFixed(2), (239.88).toFixed(2)); - assert.equal((newOwnerBalance3 - oldOwnerBalance3).toFixed(2), (579.71).toFixed(2)); - - let returnTokenUser1 = parseFloat((await marketInstance.getReturn(user1))[0][0]); - let returnTokenUser2 = parseFloat((await marketInstance.getReturn(user2))[0][0]); - let returnTokenUser3 = parseFloat((await marketInstance.getReturn(user3))[0][0]); - let returnETHUser1 = parseFloat((await marketInstance.getReturn(user1))[0][1]); - let returnETHUser2 = parseFloat((await marketInstance.getReturn(user2))[0][1]); - let returnETHUser3 = parseFloat((await marketInstance.getReturn(user3))[0][1]); - returnTokenUser1 = web3.utils.fromWei(returnTokenUser1.toString()); - returnTokenUser2 = web3.utils.fromWei(returnTokenUser2.toString()); - returnTokenUser3 = web3.utils.fromWei(returnTokenUser3.toString()); - returnETHUser1 = web3.utils.fromWei(returnETHUser1.toString()); - returnETHUser2 = web3.utils.fromWei(returnETHUser2.toString()); - returnETHUser3 = web3.utils.fromWei(returnETHUser3.toString()); - - //console.log("(parseFloat(returnTokenUser1) + returnTokenIncentiveUser1).toFixed(2)", parseFloat(returnTokenUser1)) - //console.log("(parseFloat(returnTokenUser2) + returnTokenIncentiveUser2).toFixed(2)", parseFloat(returnTokenUser2)) - //console.log("(parseFloat(returnTokenUser3) + returnTokenIncentiveUser3).toFixed(2)", parseFloat(returnTokenUser3)) - //console.log("parseFloat(returnETHUser1).toFixed(2)", parseFloat(returnETHUser1)) - //console.log("parseFloat(returnETHUser2).toFixed(2)", parseFloat(returnETHUser2)) - //console.log("parseFloat(returnETHUser3).toFixed(2)", parseFloat(returnETHUser3)) - - assert.equal((parseFloat(returnTokenUser1)).toFixed(2), (79.96).toFixed(2)); - assert.equal((parseFloat(returnTokenUser2)).toFixed(2), (239.88).toFixed(2)); - assert.equal((parseFloat(returnTokenUser3)).toFixed(2), (579.71).toFixed(2)); - assert.equal(parseFloat(returnETHUser1).toFixed(2), (2.3976).toFixed(2)); - assert.equal(parseFloat(returnETHUser2).toFixed(2), (0).toFixed(2)); - assert.equal(parseFloat(returnETHUser3).toFixed(2), (1.5984).toFixed(2)); - - const newPlotusTokenBalance = parseFloat(web3.utils.fromWei(await plotusToken.balanceOf(plotusNewInstance.address))); - const newPlotusETHBalance = parseFloat(web3.utils.fromWei(await web3.eth.getBalance(plotusNewInstance.address))); - //console.log((newPlotusTokenBalance - oldPlotusTokenBalance)); - //console.log(newPlotusETHBalance); - //console.log(parseFloat(await plotusToken.balanceOf(marketInstance.address))); - //console.log(parseFloat(web3.utils.fromWei(await web3.eth.getBalance(marketInstance.address)))); - - assert.equal((newPlotusTokenBalance - oldPlotusTokenBalance).toFixed(2), "0.45"); - assert.equal(newPlotusETHBalance, 0.004); - }); - }); -}); - -describe("4. New cases", () => { - contract("Market", async function([user1, user2, user3, user4, user5]) { - let masterInstance, marketConfig, plotusToken, tokenControllerAdd, tokenController, plotusNewAddress, plotusNewInstance; - 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")); - plotusNewInstance = await Plotus.at(plotusNewAddress); - marketConfig = await plotusNewInstance.marketUtility(); - marketConfig = await MarketConfig.at(marketConfig); - openMarkets = await plotusNewInstance.getOpenMarkets(); - //console.log(openMarkets); - marketInstance = await Market.at(openMarkets["_openMarkets"][2]); - assert.ok(marketInstance); - await increaseTime(10001); - // Transfer Tokens - await plotusToken.transfer(user2, web3.utils.toWei("5000")); - await plotusToken.transfer(user3, web3.utils.toWei("5000")); - - await marketConfig.setOptionPrice(1, 9); - await marketConfig.setOptionPrice(2, 18); - await marketConfig.setOptionPrice(3, 27); - - await plotusToken.approve(tokenController.address, web3.utils.toWei("500")); - await plotusToken.approve(tokenController.address, web3.utils.toWei("500"), { from: user2 }); - await plotusToken.approve(tokenController.address, web3.utils.toWei("500"), { from: user3 }); - }); - - it("Multiple Market claim, scenario 6,7,8", async () => { - const oldPlotusTokenBalance = parseFloat(web3.utils.fromWei(await plotusToken.balanceOf(plotusNewInstance.address))); - await marketInstance.placePrediction(plotusToken.address, web3.utils.toWei("100"), 1, 1, { from: user1 }); - await marketInstance.placePrediction("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", web3.utils.toWei("4"), 2, 2, { - from: user1, - value: web3.utils.toWei("4"), - }); - await marketInstance.placePrediction(plotusToken.address, web3.utils.toWei("400"), 3, 2, { from: user2 }); - await marketInstance.placePrediction("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", web3.utils.toWei("4"), 1, 2, { - from: user3, - value: web3.utils.toWei("4"), - }); - let predictionPointsUser1 = parseFloat(await marketInstance.getUserPredictionPoints(user1, 1)); - let predictionPointsUser1_2 = parseFloat(await marketInstance.getUserPredictionPoints(user1, 2)); - let predictionPointsUser2 = parseFloat(await marketInstance.getUserPredictionPoints(user2, 3)); - let predictionPointsUser3 = parseFloat(await marketInstance.getUserPredictionPoints(user3, 1)); - assert.equal((predictionPointsUser1 / 10000).toFixed(1), (11.10277882).toFixed(1)); - assert.equal((predictionPointsUser1_2 / 10000).toFixed(1), (93.19336834).toFixed(1)); - assert.equal((predictionPointsUser2 / 10000).toFixed(1), (62.17556139).toFixed(1)); - assert.equal((predictionPointsUser3 / 10000).toFixed(1), (186.3867367).toFixed(1)); - - const dailyMarketInstance = marketInstance; - // await increaseTime(60*60*24*2); - // await marketInstance.calculatePredictionResult(1); - - await increaseTime(60*60*2); - await plotusNewInstance.createMarket(0,0); - await plotusNewInstance.createMarket(0,1); - - openMarkets = await plotusNewInstance.getOpenMarkets(); - //console.log(openMarkets); - marketInstance = await Market.at(openMarkets["_openMarkets"][0]); - assert.ok(marketInstance); - await marketConfig.setOptionPrice(1, 9); - await marketConfig.setOptionPrice(2, 18); - await marketConfig.setOptionPrice(3, 27); - // let marketStartTime = parseFloat((await marketInstance.marketData())[0]); - // console.log("marketStartTime", marketStartTime) - // console.log(await latestTime()); - await plotusToken.approve(tokenController.address, web3.utils.toWei("500")); - await plotusToken.approve(tokenController.address, web3.utils.toWei("500"), { from: user2 }); - await plotusToken.approve(tokenController.address, web3.utils.toWei("500"), { from: user3 }); - await marketInstance.placePrediction(plotusToken.address, web3.utils.toWei("100"), 1, 1, { from: user1 }); - await marketInstance.placePrediction("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", web3.utils.toWei("4"), 2, 2, { - from: user1, - value: web3.utils.toWei("4"), - }); - await marketInstance.placePrediction(plotusToken.address, web3.utils.toWei("400"), 3, 2, { from: user2 }); - await marketInstance.placePrediction("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", web3.utils.toWei("4"), 1, 2, { - from: user3, - value: web3.utils.toWei("4"), - }); - predictionPointsUser1 = parseFloat(await marketInstance.getUserPredictionPoints(user1, 1)); - predictionPointsUser1_2 = parseFloat(await marketInstance.getUserPredictionPoints(user1, 2)); - predictionPointsUser2 = parseFloat(await marketInstance.getUserPredictionPoints(user2, 3)); - predictionPointsUser3 = parseFloat(await marketInstance.getUserPredictionPoints(user3, 1)); - assert.equal((predictionPointsUser1 / 10000).toFixed(), (11.10277882).toFixed()); - assert.equal((predictionPointsUser1_2 / 10000).toFixed(), (93.19336834).toFixed()); - assert.equal((predictionPointsUser2 / 10000).toFixed(), (62.17556139).toFixed()); - assert.equal((predictionPointsUser3 / 10000).toFixed(), (186.3867367).toFixed()); - - await increaseTime(60*60*2); - marketData = await marketInstance.getData(); - minValueOption2 = parseFloat(marketData[1][1]); - maxValueOption2 = parseFloat(marketData[2][1]); - optionValue = (minValueOption2 + maxValueOption2) / 2; - await marketInstance.calculatePredictionResult(optionValue); - - await plotusNewInstance.createMarket(0,0); - await plotusNewInstance.createMarket(0,1); - - openMarkets = await plotusNewInstance.getOpenMarkets(); - - marketInstance = await Market.at(openMarkets["_openMarkets"][0]); - assert.ok(marketInstance); - - await marketConfig.setOptionPrice(1, 9); - await marketConfig.setOptionPrice(2, 18); - await marketConfig.setOptionPrice(3, 27); - await plotusToken.approve(tokenController.address, web3.utils.toWei("500")); - await plotusToken.approve(tokenController.address, web3.utils.toWei("500"), { from: user2 }); - await plotusToken.approve(tokenController.address, web3.utils.toWei("500"), { from: user3 }); - await marketInstance.placePrediction(plotusToken.address, web3.utils.toWei("100"), 1, 1, { from: user1 }); - await marketInstance.placePrediction("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", web3.utils.toWei("4"), 2, 2, { - from: user1, - value: web3.utils.toWei("4"), - }); - await marketInstance.placePrediction(plotusToken.address, web3.utils.toWei("400"), 3, 2, { from: user2 }); - await marketInstance.placePrediction("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", web3.utils.toWei("4"), 1, 2, { - from: user3, - value: web3.utils.toWei("4"), - }); - predictionPointsUser1 = parseFloat(await marketInstance.getUserPredictionPoints(user1, 1)); - predictionPointsUser1_2 = parseFloat(await marketInstance.getUserPredictionPoints(user1, 2)); - predictionPointsUser2 = parseFloat(await marketInstance.getUserPredictionPoints(user2, 3)); - predictionPointsUser3 = parseFloat(await marketInstance.getUserPredictionPoints(user3, 1)); - assert.equal((predictionPointsUser1 / 10000).toFixed(1), (11.10277882).toFixed(1)); - assert.equal((predictionPointsUser1_2 / 10000).toFixed(1), (93.19336834).toFixed(1)); - assert.equal((predictionPointsUser2 / 10000).toFixed(1), (62.17556139).toFixed(1)); - assert.equal((predictionPointsUser3 / 10000).toFixed(1), (186.3867367).toFixed(1)); - - await increaseTime(60*60*2); - marketData = await marketInstance.getData(); - maxValueOption2 = parseFloat(marketData[2][1]); - optionValue = maxValueOption2 + 1; - await marketInstance.calculatePredictionResult(optionValue); - - await increaseTime(60*60); - - let oldOwnerBalance1 = parseFloat(web3.utils.fromWei((await plotusToken.balanceOf(user1)).toString())); - let oldOwnerBalance2 = parseFloat(web3.utils.fromWei((await plotusToken.balanceOf(user2)).toString())); - let oldOwnerBalance3 = parseFloat(web3.utils.fromWei((await plotusToken.balanceOf(user3)).toString())); - let oldOwnerETHBalance1 = parseFloat(web3.utils.fromWei((await web3.eth.getBalance(user1)).toString())); - let oldOwnerETHBalance2 = parseFloat(web3.utils.fromWei((await web3.eth.getBalance(user2)).toString())); - let oldOwnerETHBalance3 = parseFloat(web3.utils.fromWei((await web3.eth.getBalance(user3)).toString())); - - await plotusNewInstance.claimPendingReturn(10, {from: user1}) - await plotusNewInstance.claimPendingReturn(10, {from: user2}) - await plotusNewInstance.claimPendingReturn(10, {from: user3}) - - let newOwnerBalance1 = parseFloat(web3.utils.fromWei((await plotusToken.balanceOf(user1)).toString())); - let newOwnerBalance2 = parseFloat(web3.utils.fromWei((await plotusToken.balanceOf(user2)).toString())); - let newOwnerBalance3 = parseFloat(web3.utils.fromWei((await plotusToken.balanceOf(user3)).toString())); - let newOwnerETHBalance1 = parseFloat(web3.utils.fromWei((await web3.eth.getBalance(user1)).toString())); - let newOwnerETHBalance2 = parseFloat(web3.utils.fromWei((await web3.eth.getBalance(user2)).toString())); - let newOwnerETHBalance3 = parseFloat(web3.utils.fromWei((await web3.eth.getBalance(user3)).toString())); - - //console.log("(newOwnerBalance1 - oldOwnerBalance1).toFixed(2)", (newOwnerBalance1 - oldOwnerBalance1).toFixed(2)) - //console.log("(newOwnerBalance2 - oldOwnerBalance2).toFixed(2)", (newOwnerBalance2 - oldOwnerBalance2).toFixed(2)) - //console.log("(newOwnerBalance3 - oldOwnerBalance3).toFixed(2)", (newOwnerBalance3 - oldOwnerBalance3).toFixed(2)) - assert.equal((newOwnerBalance1 - oldOwnerBalance1).toFixed(2), (339.83).toFixed(2)); - assert.equal((newOwnerBalance2 - oldOwnerBalance2).toFixed(2), (659.67).toFixed(2)); - assert.equal((newOwnerBalance3 - oldOwnerBalance3).toFixed(2), (0).toFixed(2)); - - assert.equal((newOwnerETHBalance1 - oldOwnerETHBalance1).toFixed(2), (7.992).toFixed(2)); - expect((newOwnerETHBalance2 - oldOwnerETHBalance2)).to.be.closeTo(3.19, 3.2);//3.1968 - expect((newOwnerETHBalance3 - oldOwnerETHBalance3)).to.be.closeTo(4.7, 4.8);//4.7952 - - await increaseTime(60*60*24*2); - await dailyMarketInstance.calculatePredictionResult(1); - await increaseTime(60*60*24); - - oldOwnerBalance1 = parseFloat(web3.utils.fromWei((await plotusToken.balanceOf(user1)).toString())); - oldOwnerBalance2 = parseFloat(web3.utils.fromWei((await plotusToken.balanceOf(user2)).toString())); - oldOwnerBalance3 = parseFloat(web3.utils.fromWei((await plotusToken.balanceOf(user3)).toString())); - oldOwnerETHBalance1 = parseFloat(web3.utils.fromWei((await web3.eth.getBalance(user1)).toString())); - oldOwnerETHBalance2 = parseFloat(web3.utils.fromWei((await web3.eth.getBalance(user2)).toString())); - oldOwnerETHBalance3 = parseFloat(web3.utils.fromWei((await web3.eth.getBalance(user3)).toString())); - - await plotusNewInstance.claimPendingReturn(10, {from: user1}) - await plotusNewInstance.claimPendingReturn(10, {from: user2}) - await plotusNewInstance.claimPendingReturn(10, {from: user3}) - - newOwnerBalance1 = parseFloat(web3.utils.fromWei((await plotusToken.balanceOf(user1)).toString())); - newOwnerBalance2 = parseFloat(web3.utils.fromWei((await plotusToken.balanceOf(user2)).toString())); - newOwnerBalance3 = parseFloat(web3.utils.fromWei((await plotusToken.balanceOf(user3)).toString())); - newOwnerETHBalance1 = parseFloat(web3.utils.fromWei((await web3.eth.getBalance(user1)).toString())); - newOwnerETHBalance2 = parseFloat(web3.utils.fromWei((await web3.eth.getBalance(user2)).toString())); - newOwnerETHBalance3 = parseFloat(web3.utils.fromWei((await web3.eth.getBalance(user3)).toString())); - - //console.log("(newOwnerBalance1 - oldOwnerBalance1).toFixed(2)", (newOwnerBalance1 - oldOwnerBalance1).toFixed(2)) - //console.log("(newOwnerBalance2 - oldOwnerBalance2).toFixed(2)", (newOwnerBalance2 - oldOwnerBalance2).toFixed(2)) - //console.log("(newOwnerBalance3 - oldOwnerBalance3).toFixed(2)", (newOwnerBalance3 - oldOwnerBalance3).toFixed(2)) - assert.equal((newOwnerBalance1 - oldOwnerBalance1).toFixed(2), (108.9406362).toFixed(2)); - assert.equal((newOwnerBalance2 - oldOwnerBalance2).toFixed(2), (239.88).toFixed(2)); - assert.equal((newOwnerBalance3 - oldOwnerBalance3).toFixed(2), (150.9293638).toFixed(2)); - - expect((newOwnerETHBalance1 - oldOwnerETHBalance1)).to.be.closeTo(2.2, 2.3);//2.487461386 - assert.equal(((newOwnerETHBalance2 - oldOwnerETHBalance2).toFixed(2))*1, ((0).toFixed(2))*1); - expect((newOwnerETHBalance3 - oldOwnerETHBalance3)).to.be.closeTo(5.5, 5.6);//5.504538614 - - }); - }); -}) \ No newline at end of file diff --git a/test/09_multiplier.test.js b/test/09_multiplier.test.js new file mode 100644 index 000000000..23f600a12 --- /dev/null +++ b/test/09_multiplier.test.js @@ -0,0 +1,368 @@ +const { assert } = require("chai"); +const OwnedUpgradeabilityProxy = artifacts.require("OwnedUpgradeabilityProxy"); +const Master = artifacts.require("Master"); +const MemberRoles = artifacts.require("MemberRoles"); +const PlotusToken = artifacts.require("MockPLOT"); +const MockConfig = artifacts.require("MockConfig"); //mock +const Governance = artifacts.require("Governance"); +const AllMarkets = artifacts.require("MockAllMarkets"); +const TokenController = artifacts.require("MockTokenController"); +const MarketCreationRewards = artifacts.require('MarketCreationRewards'); + +const ethAddress = "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE"; +const signAndExecuteMetaTx = require("./utils/signAndExecuteMetaTx.js").signAndExecuteMetaTx; +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 encode3 = require("./utils/encoder.js").encode3; +const encode1 = require("./utils/encoder.js").encode1; +const gvProposal = require("./utils/gvProposal.js").gvProposalWithIncentiveViaTokenHolder; +const { toHex, toWei, toChecksumAddress } = require("./utils/ethTools"); +const to8Power = (number) => String(parseFloat(number) * 1e8); +let privateKeyList = ["fb437e3e01939d9d4fef43138249f23dc1d0852e69b0b5d1647c087f869fabbd","7c85a1f1da3120c941b83d71a154199ee763307683f206b98ad92c3b4e0af13e","ecc9b35bf13bd5459350da564646d05c5664a7476fe5acdf1305440f88ed784c","f4470c3fca4dbef1b2488d016fae25978effc586a1f83cb29ac8cb6ab5bc2d50","141319b1a84827e1046e93741bf8a9a15a916d49684ab04925ac4ce4573eea23","d54b606094287758dcf19064a8d91c727346aadaa9388732e73c4315b7c606f9","49030e42ce4152e715a7ddaa10e592f8e61d00f70ef11f48546711f159d985df","b96761b1e7ebd1e8464a78a98fe52f53ce6035c32b4b2b12307a629a551ff7cf","d4786e2581571c863c7d12231c3afb6d4cef390c0ac9a24b243293721d28ea95","ed28e3d3530544f1cf2b43d1956b7bd13b63c612d963a8fb37387aa1a5e11460","05b127365cf115d4978a7997ee98f9b48f0ddc552b981c18aa2ee1b3e6df42c6","9d11dd6843f298b01b34bd7f7e4b1037489871531d14b58199b7cba1ac0841e6","f79e90fa4091de4fc2ec70f5bf67b24393285c112658e0d810e6bd711387fbb9","99f1fc0f09230ce745b6a256ba7082e6e51a2907abda3d9e735a5c8188bb4ba1","477f86cce983b9c91a36fdcd4a7ce21144a08dee9b1aafb91b9c70e57f717ce6","b03d2e6bb4a7d71c66a66ff9e9c93549cae4b593f634a4ea2a1f79f94200f5b4","9ddc0f53a81e631dcf39d5155f41ec12ed551b731efc3224f410667ba07b37dc","cf087ff9ae7c9954ad8612d071e5cdf34a6024ee1ae477217639e63a802a53dd","b64f62b94babb82cc78d3d1308631ae221552bb595202fc1d267e1c29ce7ba60","a91e24875f8a534497459e5ccb872c4438be3130d8d74b7e1104c5f94cdcf8c2","4f49f3d029eeeb3fed14d59625acd088b6b34f3b41c527afa09d29e4a7725c32","179795fd7ac7e7efcba3c36d539a1e8659fb40d77d0a3fab2c25562d99793086","4ba37d0b40b879eceaaca2802a1635f2e6d86d5c31e3ff2d2fd13e68dd2a6d3d","6b7f5dfba9cd3108f1410b56f6a84188eee23ab48a3621b209a67eea64293394","870c540da9fafde331a3316cee50c17ad76ddb9160b78b317bef2e6f6fc4bac0","470b4cccaea895d8a5820aed088357e380d66b8e7510f0a1ea9b575850160241","8a55f8942af0aec1e0df3ab328b974a7888ffd60ded48cc6862013da0f41afbc","2e51e8409f28baf93e665df2a9d646a1bf9ac8703cbf9a6766cfdefa249d5780","99ef1a23e95910287d39493d8d9d7d1f0b498286f2b1fdbc0b01495f10cf0958","6652200c53a4551efe2a7541072d817562812003f9d9ef0ec17995aa232378f8","39c6c01194df72dda97da2072335c38231ced9b39afa280452afcca901e73643","12097e411d948f77b7b6fa4656c6573481c1b4e2864c1fca9d5b296096707c45","cbe53bf1976aee6cec830a848c6ac132def1503cffde82ccfe5bd15e75cbaa72","eeab5dcfff92dbabb7e285445aba47bd5135a4a3502df59ac546847aeb5a964f","5ea8279a578027abefab9c17cef186cccf000306685e5f2ee78bdf62cae568dd","0607767d89ad9c7686dbb01b37248290b2fa7364b2bf37d86afd51b88756fe66","e4fd5f45c08b52dae40f4cdff45e8681e76b5af5761356c4caed4ca750dc65cd","145b1c82caa2a6d703108444a5cf03e9cb8c3cd3f19299582a564276dbbba734","736b22ec91ae9b4b2b15e8d8c220f6c152d4f2228f6d46c16e6a9b98b4733120","ac776cb8b40f92cdd307b16b83e18eeb1fbaa5b5d6bd992b3fda0b4d6de8524c","65ba30e2202fdf6f37da0f7cfe31dfb5308c9209885aaf4cef4d572fd14e2903","54e8389455ec2252de063e83d3ce72529d674e6d2dc2070661f01d4f76b63475","fbbbfb525dd0255ee332d51f59648265aaa20c2e9eff007765cf4d4a6940a849","8de5e418f34d04f6ea947ce31852092a24a705862e6b810ca9f83c2d5f9cda4d","ea6040989964f012fd3a92a3170891f5f155430b8bbfa4976cde8d11513b62d9","14d94547b5deca767137fbd14dae73e888f3516c742fad18b83be333b38f0b88","47f05203f6368d56158cda2e79167777fc9dcb0c671ef3aabc205a1636c26a29"]; + +// Multiplier Sheet +describe("new_Multiplier 1. Multiplier Sheet PLOT Prediction", () => { + let masterInstance, + plotusToken, + mockMarketConfig, + MockUniswapRouterInstance, + tokenControllerAdd, + tokenController, + plotusNewAddress, + plotusNewInstance, + governance, + mockUniswapV2Pair, + mockUniswapFactory, + weth, + allMarkets, + marketUtility, + mockChainLinkAggregator, + marketIncentives; + let marketId = 1; + let predictionPointsBeforeUser1, predictionPointsBeforeUser2, predictionPointsBeforeUser3, predictionPointsBeforeUser4; + + contract("AllMarkets", async function ([user0, user1, user2, user3, user4, user5, userMarketCreator]) { + 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); + 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); + marketIncentives = await MarketCreationRewards.at(await masterInstance.getLatestAddress(toHex("MC"))); + mockMarketConfig = await masterInstance.getLatestAddress(web3.utils.toHex("MU")); + mockMarketConfig = await MockConfig.at(mockMarketConfig); + allMarkets = await AllMarkets.at(await masterInstance.getLatestAddress(web3.utils.toHex("AM"))); + marketId = 6; + await increaseTime(4 * 60 * 60 + 1); + await plotusToken.transfer(userMarketCreator, toWei(1000)); + await plotusToken.approve(allMarkets.address, toWei(1000), { from: userMarketCreator }); + await allMarkets.createMarket(0, 0, { from: userMarketCreator }); + marketId++; + }); + it("1.1 Position without User levels", async () => { + await plotusToken.transfer(user1, toWei("100")); + await plotusToken.transfer(user2, toWei("400")); + await plotusToken.transfer(user3, toWei("100")); + await plotusToken.transfer(user4, toWei("100")); + await plotusToken.transfer(user5, toWei("1000")); + + await plotusToken.approve(allMarkets.address, toWei("10000"), { from: user1 }); + await plotusToken.approve(allMarkets.address, toWei("10000"), { from: user2 }); + await plotusToken.approve(allMarkets.address, toWei("10000"), { from: user3 }); + await plotusToken.approve(allMarkets.address, toWei("10000"), { from: user4 }); + await plotusToken.approve(allMarkets.address, toWei("10000"), { from: user5 }); + + // await allMarkets.deposit(toWei(100), { from: user1 }); + // await allMarkets.deposit(toWei(400), { from: user2 }); + // await allMarkets.deposit(toWei(100), { from: user3 }); + // await allMarkets.deposit(toWei(100), { from: user4 }); + // await allMarkets.deposit(toWei(10), { from: user5 }); + + await mockMarketConfig.setNextOptionPrice(9); + assert.equal((await mockMarketConfig.getOptionPrice(marketId, 1)) / 1, 9); + // await allMarkets.depositAndPlacePrediction(toWei(100), marketId, plotusToken.address, to8Power("100"), 1, { from: user3 }); + let functionSignature = encode3("depositAndPlacePrediction(uint,uint,address,uint64,uint256)", toWei(100), marketId, plotusToken.address, to8Power("100"), 1); + await signAndExecuteMetaTx( + privateKeyList[3], + user3, + functionSignature, + allMarkets, + "AM" + ); + await mockMarketConfig.setNextOptionPrice(18); + assert.equal((await mockMarketConfig.getOptionPrice(marketId, 2)) / 1, 18); + // assert.equal((await allMarkets.getMarketData(marketId))._optionPrice[1] / 1, 18); + // await allMarkets.depositAndPlacePrediction(toWei(100), marketId, plotusToken.address, to8Power("100"), 2, { from: user1 }); + functionSignature = encode3("depositAndPlacePrediction(uint,uint,address,uint64,uint256)", toWei(100), marketId, plotusToken.address, to8Power("100"), 2); + await signAndExecuteMetaTx( + privateKeyList[1], + user1, + functionSignature, + allMarkets, + "AM" + ); + // await allMarkets.depositAndPlacePrediction(toWei(400), marketId, plotusToken.address, to8Power("400"), 2, { from: user2 }); + functionSignature = encode3("depositAndPlacePrediction(uint,uint,address,uint64,uint256)", toWei(400), marketId, plotusToken.address, to8Power("400"), 2); + await signAndExecuteMetaTx( + privateKeyList[2], + user2, + functionSignature, + allMarkets, + "AM" + ); + await mockMarketConfig.setNextOptionPrice(27); + assert.equal((await mockMarketConfig.getOptionPrice(marketId, 3)) / 1, 27); + // assert.equal((await allMarkets.getMarketData(marketId))._optionPrice[2] / 1, 27); + // await allMarkets.depositAndPlacePrediction(toWei(100), marketId, plotusToken.address, to8Power("100"), 3, { from: user4 }); + functionSignature = encode3("depositAndPlacePrediction(uint,uint,address,uint64,uint256)", toWei(100), marketId, plotusToken.address, to8Power("100"), 3); + await signAndExecuteMetaTx( + privateKeyList[4], + user4, + functionSignature, + allMarkets, + "AM" + ); + // await allMarkets.depositAndPlacePrediction(toWei(1000), marketId, plotusToken.address, to8Power("1000"), 3, { from: user5 }); + functionSignature = encode3("depositAndPlacePrediction(uint,uint,address,uint64,uint256)", toWei(1000), marketId, plotusToken.address, to8Power("1000"), 3); + await signAndExecuteMetaTx( + privateKeyList[5], + user5, + functionSignature, + allMarkets, + "AM" + ); + predictionPointsBeforeUser1 = (await allMarkets.getUserPredictionPoints(user1, marketId, 2)) / 1e5; + predictionPointsBeforeUser2 = (await allMarkets.getUserPredictionPoints(user2, marketId, 2)) / 1e5; + predictionPointsBeforeUser3 = (await allMarkets.getUserPredictionPoints(user3, marketId, 1)) / 1e5; + predictionPointsBeforeUser4 = (await allMarkets.getUserPredictionPoints(user4, marketId, 3)) / 1e5; + predictionPointsBeforeUser5 = (await allMarkets.getUserPredictionPoints(user5, marketId, 3)) / 1e5; + // console.log( // predictionPointsBeforeUser1, // predictionPointsBeforeUser2, // predictionPointsBeforeUser3, // predictionPointsBeforeUser4, // predictionPointsBeforeUser5 // ); + + const expectedPredictionPoints = [5444.44444, 21777.77777, 10888.88888, 3629.62963, 36296.2963]; + const predictionPointArray = [ + predictionPointsBeforeUser1, + predictionPointsBeforeUser2, + predictionPointsBeforeUser3, + predictionPointsBeforeUser4, + predictionPointsBeforeUser5, + ]; + for (let i = 0; i < 5; i++) { + assert.equal(parseInt(expectedPredictionPoints[i]), parseInt(predictionPointArray[i])); + } + + await increaseTime(8 * 60 * 60); + let balanceBefore = await plotusToken.balanceOf(marketIncentives.address); + balanceBefore = balanceBefore*1; + await allMarkets.postResultMock(1, marketId); + await increaseTime(8 * 60 * 60); + let balanceAfter = await plotusToken.balanceOf(marketIncentives.address); + balanceAfter = balanceAfter*1; + let commission = 0; + let creationRewardDaoCommission = 17.999; + assert.equal(~~(balanceAfter/1e15), balanceBefore + creationRewardDaoCommission*1e3); + }); + + it("1.2 Positions After increasing user levels", async () => { + await increaseTime(4 * 60 * 60 + 1); + + let userLevels = []; + let multipliers = []; + for(let i = 1; i <= 25; i++) { + userLevels.push(i); + multipliers.push(5*i); + } + let actionHash = encode1( + ['uint256[]', 'uint256[]'], + [ + userLevels, + multipliers + ] + ); + await gvProposal(23, actionHash, memberRoles, governance, 1, 0); + + await assertRevert(mockMarketConfig.setMultiplierLevels(userLevels, multipliers)); + + await allMarkets.createMarket(0, 0, { from: userMarketCreator }) + marketId++; + + await mockMarketConfig.setUserLevel(user1, 1); + await mockMarketConfig.setUserLevel(user2, 2); + await mockMarketConfig.setUserLevel(user3, 5); + await mockMarketConfig.setUserLevel(user4, 10); + await mockMarketConfig.setUserLevel(user5, 22); + await plotusToken.transfer(user1, toWei("100")); + await plotusToken.transfer(user2, toWei("400")); + await plotusToken.transfer(user3, toWei("100")); + await plotusToken.transfer(user4, toWei("100")); + await plotusToken.transfer(user5, toWei("1000")); + + await plotusToken.approve(allMarkets.address, toWei("10000"), { from: user1 }); + await plotusToken.approve(allMarkets.address, toWei("10000"), { from: user2 }); + await plotusToken.approve(allMarkets.address, toWei("10000"), { from: user3 }); + await plotusToken.approve(allMarkets.address, toWei("10000"), { from: user4 }); + await plotusToken.approve(allMarkets.address, toWei("10000"), { from: user5 }); + + // await allMarkets.deposit(toWei(100), { from: user1 }); + // await allMarkets.deposit(toWei(400), { from: user2 }); + // await allMarkets.deposit(toWei(100), { from: user3 }); + // await allMarkets.deposit(toWei(100), { from: user4 }); + // await allMarkets.deposit(toWei(10), { from: user5 }); + + await mockMarketConfig.setNextOptionPrice(9); + assert.equal((await mockMarketConfig.getOptionPrice(marketId, 1)) / 1, 9); + // assert.equal((await allMarkets.getMarketData(marketId))._optionPrice[0] / 1, 9); + // await allMarkets.depositAndPlacePrediction(toWei(100), marketId, plotusToken.address, to8Power("100"), 1, { from: user3 }); + let functionSignature = encode3("depositAndPlacePrediction(uint,uint,address,uint64,uint256)", toWei(100), marketId, plotusToken.address, to8Power("100"), 1); + await signAndExecuteMetaTx( + privateKeyList[3], + user3, + functionSignature, + allMarkets, + "AM" + ); + await mockMarketConfig.setNextOptionPrice(18); + assert.equal((await mockMarketConfig.getOptionPrice(marketId, 2)) / 1, 18); + // assert.equal((await allMarkets.getMarketData(marketId))._optionPrice[1] / 1, 18); + // await allMarkets.depositAndPlacePrediction(toWei(100), marketId, plotusToken.address, to8Power("100"), 2, { from: user1 }); + functionSignature = encode3("depositAndPlacePrediction(uint,uint,address,uint64,uint256)", toWei(100), marketId, plotusToken.address, to8Power("100"), 2); + await signAndExecuteMetaTx( + privateKeyList[1], + user1, + functionSignature, + allMarkets, + "AM" + ); + // await allMarkets.depositAndPlacePrediction(toWei(400), marketId, plotusToken.address, to8Power("400"), 2, { from: user2 }); + functionSignature = encode3("depositAndPlacePrediction(uint,uint,address,uint64,uint256)", toWei(400), marketId, plotusToken.address, to8Power("400"), 2); + await signAndExecuteMetaTx( + privateKeyList[2], + user2, + functionSignature, + allMarkets, + "AM" + ); + await mockMarketConfig.setNextOptionPrice(27); + assert.equal((await mockMarketConfig.getOptionPrice(marketId, 3)) / 1, 27); + // assert.equal((await allMarkets.getMarketData(marketId))._optionPrice[2] / 1, 27); + // await allMarkets.depositAndPlacePrediction(toWei(100), marketId, plotusToken.address, to8Power("100"), 3, { from: user4 }); + functionSignature = encode3("depositAndPlacePrediction(uint,uint,address,uint64,uint256)", toWei(100), marketId, plotusToken.address, to8Power("100"), 3); + await signAndExecuteMetaTx( + privateKeyList[4], + user4, + functionSignature, + allMarkets, + "AM" + ); + // await allMarkets.depositAndPlacePrediction(toWei(1000), marketId, plotusToken.address, to8Power("1000"), 3, { from: user5 }); + functionSignature = encode3("depositAndPlacePrediction(uint,uint,address,uint64,uint256)", toWei(1000), marketId, plotusToken.address, to8Power("1000"), 3); + await signAndExecuteMetaTx( + privateKeyList[5], + user5, + functionSignature, + allMarkets, + "AM" + ); + predictionPointsBeforeUser1 = (await allMarkets.getUserPredictionPoints(user1, marketId, 2)) / 1e5; + predictionPointsBeforeUser2 = (await allMarkets.getUserPredictionPoints(user2, marketId, 2)) / 1e5; + predictionPointsBeforeUser3 = (await allMarkets.getUserPredictionPoints(user3, marketId, 1)) / 1e5; + predictionPointsBeforeUser4 = (await allMarkets.getUserPredictionPoints(user4, marketId, 3)) / 1e5; + predictionPointsBeforeUser5 = (await allMarkets.getUserPredictionPoints(user5, marketId, 3)) / 1e5; + // console.log( // predictionPointsBeforeUser1, // predictionPointsBeforeUser2, // predictionPointsBeforeUser3, // predictionPointsBeforeUser4, // predictionPointsBeforeUser5 // ); + + const expectedPredictionPoints = [5716.66666, 23955.55555, 13611.11111, 5444.44444, 76222.22222]; + const predictionPointArray = [ + predictionPointsBeforeUser1, + predictionPointsBeforeUser2, + predictionPointsBeforeUser3, + predictionPointsBeforeUser4, + predictionPointsBeforeUser5, + ]; + for (let i = 0; i < 5; i++) { + assert.equal(parseInt(expectedPredictionPoints[i]), parseInt(predictionPointArray[i])); + } + + await increaseTime(8 * 60 * 60); + let balanceBefore = await plotusToken.balanceOf(marketIncentives.address); + balanceBefore = balanceBefore*1; + await allMarkets.postResultMock(1, marketId); + await increaseTime(8 * 60 * 60); + let balanceAfter = await plotusToken.balanceOf(marketIncentives.address); + balanceAfter = balanceAfter*1; + let commission = 0; + let creationRewardDaoCommission = 17.9999; + assert.equal(~~(balanceAfter/1e15), ~~(balanceBefore/1e15 + creationRewardDaoCommission*1e3)); + }); + // it("1.2 Positions After increasing user levels", async () => { + // await allMarkets.createMarket(0, 0); + // marketId++; + + // await plotusToken.transfer(user2, toWei(400 + 1600)); + // await plotusToken.transfer(user3, toWei(100 + 1100)); + // await plotusToken.transfer(user4, toWei(100 + 1100)); + // await plotusToken.transfer(user5, toWei(10 + 1100)); + + // await plotusToken.approve(tokenController.address, toWei("10000"), { from: user1 }); + // await plotusToken.approve(tokenController.address, toWei("10000"), { from: user2 }); + // await plotusToken.approve(tokenController.address, toWei("10000"), { from: user3 }); + // await plotusToken.approve(tokenController.address, toWei("10000"), { from: user4 }); + // await plotusToken.approve(tokenController.address, toWei("10000"), { from: user5 }); + // await tokenController.lock("0x534d", toWei("1100"), 86400 * 30, { from: user1 }); + // await tokenController.lock("0x534d", toWei("1600"), 86400 * 30, { from: user2 }); + // await tokenController.lock("0x534d", toWei("1100"), 86400 * 30, { from: user3 }); + // await tokenController.lock("0x534d", toWei("1100"), 86400 * 30, { from: user4 }); + // await tokenController.lock("0x534d", toWei("1100"), 86400 * 30, { from: user5 }); + + // await plotusToken.approve(allMarkets.address, toWei("10000"), { from: user1 }); + // await plotusToken.approve(allMarkets.address, toWei("10000"), { from: user2 }); + // await plotusToken.approve(allMarkets.address, toWei("10000"), { from: user3 }); + // await plotusToken.approve(allMarkets.address, toWei("10000"), { from: user4 }); + // await plotusToken.approve(allMarkets.address, toWei("10000"), { from: user5 }); + + // await allMarkets.deposit(toWei(100), { from: user1 }); + // await allMarkets.deposit(toWei(400), { from: user2 }); + // await allMarkets.deposit(toWei(100), { from: user3 }); + // await allMarkets.deposit(toWei(100), { from: user4 }); + // await allMarkets.deposit(toWei(10), { from: user5 }); + + // await mockMarketConfig.setNextOptionPrice(9); + // await allMarkets.placePrediction(marketId, plotusToken.address, to8Power("100"), 1, { from: user3 }); + + // await mockMarketConfig.setNextOptionPrice(18); + // await allMarkets.placePrediction(marketId, plotusToken.address, to8Power("100"), 2, { from: user1 }); + // await allMarkets.placePrediction(marketId, plotusToken.address, to8Power("400"), 2, { from: user2 }); + + // await mockMarketConfig.setNextOptionPrice(27); + // await allMarkets.placePrediction(marketId, plotusToken.address, to8Power("100"), 3, { from: user4 }); + // await allMarkets.placePrediction(marketId, plotusToken.address, to8Power("10"), 3, { from: user5 }); + + // predictionPointsBeforeUser1 = parseFloat(await allMarkets.getUserPredictionPoints(user1, marketId, 2)) / 1e5; + // predictionPointsBeforeUser2 = parseFloat(await allMarkets.getUserPredictionPoints(user2, marketId, 2)) / 1e5; + // predictionPointsBeforeUser3 = parseFloat(await allMarkets.getUserPredictionPoints(user3, marketId, 1)) / 1e5; + // predictionPointsBeforeUser4 = parseFloat(await allMarkets.getUserPredictionPoints(user4, marketId, 3)) / 1e5; + // predictionPointsBeforeUser5 = parseFloat(await allMarkets.getUserPredictionPoints(user5, marketId, 3)) / 1e5; + // // console.log( // predictionPointsBeforeUser1, // predictionPointsBeforeUser2, // predictionPointsBeforeUser3, // predictionPointsBeforeUser4, // predictionPointsBeforeUser5 // ); + + // const expectedPredictionPoints = [116.6083333, 310.9555556, 233.2166667, 77.73888889, 3.701851852]; + // const predictionPointArray = [ + // predictionPointsBeforeUser1, + // predictionPointsBeforeUser2, + // predictionPointsBeforeUser3, + // predictionPointsBeforeUser4, + // predictionPointsBeforeUser5, + // ]; + // for (let i = 0; i < 5; i++) { + // assert.equal(parseInt(expectedPredictionPoints[i]), parseInt(predictionPointArray[i])); + // } + + // await increaseTime(8 * 60 * 60); + // await allMarkets.postResultMock(1, marketId); + // await increaseTime(8 * 60 * 60); + // }); + }); +}); diff --git a/test/10_plotus.js b/test/10_plotus.js deleted file mode 100644 index 072154e45..000000000 --- a/test/10_plotus.js +++ /dev/null @@ -1,381 +0,0 @@ -const { assert } = require("chai"); - -const OwnedUpgradeabilityProxy = artifacts.require("OwnedUpgradeabilityProxy"); -const Market = artifacts.require("MockMarket"); -const Plotus = artifacts.require("MarketRegistry"); -const Master = artifacts.require("Master"); -const MarketConfig = artifacts.require("MockConfig"); -const PlotusToken = artifacts.require("MockPLOT"); -const Governance = artifacts.require("Governance"); -const TokenController = artifacts.require("TokenController"); -const MockchainLinkBTC = artifacts.require("MockChainLinkAggregator"); -const BLOT = artifacts.require("BLOT"); -const MockUniswapRouter = artifacts.require("MockUniswapRouter"); -const BigNumber = require("bignumber.js"); -const { increaseTimeTo } = require("./utils/increaseTime.js"); - -const web3 = Market.web3; -const assertRevert = require("./utils/assertRevert.js").assertRevert; -const increaseTime = require("./utils/increaseTime.js").increaseTime; -const latestTime = require("./utils/latestTime.js").latestTime; -// get etherum accounts -// swap ether with LOT -let timeNow, - marketData, - expireTme, - priceOption1, - priceOption2, - priceOption3, - option1RangeMIN, - option1RangeMAX, - option2RangeMIN, - option2RangeMAX, - option3RangeMIX, - marketStatus, - option3RangeMAX, governance, - marketETHBalanceBeforeDispute; - -contract("Market", async function([user1, user2, user3, user4, user5, user6, user7, user8, user9, user10, user11]) { - describe("Place the predictions with ether", async () => { - it("0.0", async () => { - masterInstance = await OwnedUpgradeabilityProxy.deployed(); - masterInstance = await Master.at(masterInstance.address); - plotusToken = await PlotusToken.deployed(); - BLOTInstance = await BLOT.deployed(); - MockUniswapRouterInstance = await MockUniswapRouter.deployed(); - plotusNewAddress = await masterInstance.getLatestAddress(web3.utils.toHex("PL")); - tokenController =await TokenController.at(await masterInstance.getLatestAddress(web3.utils.toHex("TC"))); - governance = await masterInstance.getLatestAddress(web3.utils.toHex("GV")); - governance = await Governance.at(governance); - plotusNewInstance = await Plotus.at(plotusNewAddress); - marketConfig = await plotusNewInstance.marketUtility(); - marketConfig = await MarketConfig.at(marketConfig); - // console.log(await plotusNewInstance.getOpenMarkets()); - openMarkets = await plotusNewInstance.getOpenMarkets(); - timeNow = await latestTime(); - marketInstance = await Market.at(openMarkets["_openMarkets"][0]); - - marketData = await marketInstance.getData(); - // expireTme = parseFloat(marketData._expireTime); - // console.log("expireTme", expireTme); - // console.log("timeNow", timeNow); - - priceOption1 = parseFloat(await marketInstance.getOptionPrice(1)); - priceOption2 = parseFloat(await marketInstance.getOptionPrice(2)); - priceOption3 = parseFloat(await marketInstance.getOptionPrice(3)); - - option1RangeMIN = parseFloat(marketData[1][0]); - option1RangeMAX = parseFloat(marketData[2][0]); - option2RangeMIN = parseFloat(marketData[1][1]); - option2RangeMAX = parseFloat(marketData[2][1]); - option3RangeMIX = parseFloat(marketData[1][2]); - option3RangeMAX = parseFloat(marketData[2][2]); - }); - - it("Should not allow to initiate market from unauthorized address", async() => { - await assertRevert(marketInstance.initiate(1,1,1,1)); - }) - - it("0.1 Assert values from getData()", async () => { - assert.equal(option1RangeMIN, 0); - assert.equal(option1RangeMAX, 934999999999); - assert.equal(option2RangeMIN, 935000000000); - assert.equal(option2RangeMAX, 937500000000); - assert.equal(option3RangeMIX, 937500000001); - assert.equal(option3RangeMAX, 1.157920892373162e77); - assert.equal(parseFloat(marketData._optionPrice[0]), priceOption1); - assert.equal(parseFloat(marketData._optionPrice[1]), priceOption2); - assert.equal(parseFloat(marketData._optionPrice[2]), priceOption3); - assert.equal(marketData._marketCurrency, openMarkets._marketCurrencies[0]); - assert.equal(parseFloat(marketData._ethStaked[0]), 0); - assert.equal(parseFloat(marketData._ethStaked[1]), 0); - assert.equal(parseFloat(marketData._ethStaked[2]), 0); - assert.equal(parseFloat(marketData._predictionTime), 3600); - }); - - it("0.2", async () => { - await increaseTime(10001); - assert.ok(marketInstance); - - // setting option price in eth - await marketConfig.setOptionPrice(1, 9); - await marketConfig.setOptionPrice(2, 18); - await marketConfig.setOptionPrice(3, 27); - - marketData = await marketInstance.getData(); - priceOption1 = parseFloat(await marketInstance.getOptionPrice(1)); - priceOption2 = parseFloat(await marketInstance.getOptionPrice(2)); - priceOption3 = parseFloat(await marketInstance.getOptionPrice(3)); - }); - - it("0.3 Assert values from getData()", async () => { - assert.equal(parseFloat(marketData._optionPrice[0]), priceOption1); - assert.equal(parseFloat(marketData._optionPrice[1]), priceOption2); - assert.equal(parseFloat(marketData._optionPrice[2]), priceOption3); - assert.equal(parseFloat(marketData._optionPrice[0]), 9); - assert.equal(parseFloat(marketData._optionPrice[1]), 18); - assert.equal(parseFloat(marketData._optionPrice[2]), 27); - }); - - it("0.4 Assert values from getData()", async () => { - // set price - // user 1 - // set price lot - await MockUniswapRouterInstance.setPrice("1000000000000000"); - await marketConfig.setPrice("1000000000000000"); - await plotusToken.approve(tokenController.address, "100000000000000000000", { - from: user1, - }); - await marketInstance.placePrediction(plotusToken.address, "100000000000000000000", 2, 1, { from: user1 }); - - // user 2 - await MockUniswapRouterInstance.setPrice("2000000000000000"); - await marketConfig.setPrice("2000000000000000"); - await plotusToken.transfer(user2, "500000000000000000000"); - - await plotusToken.approve(tokenController.address, "400000000000000000000", { - from: user2, - }); - await marketInstance.placePrediction(plotusToken.address, "400000000000000000000", 2, 2, { from: user2 }); - - // user 3 - await MockUniswapRouterInstance.setPrice("1000000000000000"); - await marketConfig.setPrice("1000000000000000"); - await plotusToken.transfer(user3, "500000000000000000000"); - await plotusToken.approve(tokenController.address, "210000000000000000000", { - from: user3, - }); - await marketInstance.placePrediction(plotusToken.address, "210000000000000000000", 2, 2, { from: user3 }); - // user 4 - - await MockUniswapRouterInstance.setPrice("15000000000000000"); - await marketConfig.setPrice("15000000000000000"); - - await plotusToken.transfer(user4, "200000000000000000000"); - - await plotusToken.approve(tokenController.address, "123000000000000000000", { - from: user4, - }); - await marketInstance.placePrediction(plotusToken.address, "123000000000000000000", 3, 3, { from: user4 }); - - // user 5 - await MockUniswapRouterInstance.setPrice("12000000000000000"); - await marketConfig.setPrice("12000000000000000"); - await marketInstance.placePrediction("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", "1000000000000000000", 1, 4, { - value: "1000000000000000000", - from: user5, - }); - - // user 6 - await MockUniswapRouterInstance.setPrice("14000000000000000"); - await marketConfig.setPrice("14000000000000000"); - await marketInstance.placePrediction("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", "2000000000000000000", 1, 5, { - value: "2000000000000000000", - from: user6, - }); - // user 7 - await MockUniswapRouterInstance.setPrice("10000000000000000"); - await marketConfig.setPrice("10000000000000000"); - - await marketInstance.placePrediction("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", "1000000000000000000", 2, 2, { - value: "1000000000000000000", - from: user7, - }); - // user 8 - await MockUniswapRouterInstance.setPrice("45000000000000000"); - await marketConfig.setPrice("45000000000000000"); - await marketInstance.placePrediction("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", "3000000000000000000", 3, 3, { - value: "3000000000000000000", - from: user8, - }); - // user 9 - await MockUniswapRouterInstance.setPrice("51000000000000000"); - await marketConfig.setPrice("51000000000000000"); - await marketInstance.placePrediction("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", "1000000000000000000", 3, 1, { - value: "1000000000000000000", - from: user9, - }); - // user 10 - await MockUniswapRouterInstance.setPrice("12000000000000000"); - await marketConfig.setPrice("12000000000000000"); - await marketInstance.placePrediction("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", "2000000000000000000", 2, 4, { - value: "2000000000000000000", - from: user10, - }); - }); - - it("0.5 Cannot place prediction more than max prediction amount", async ()=> { - await assertRevert(marketInstance.placePrediction("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", "29000000000000000000", 2, 4, { - value: "29000000000000000000", - from: user10 - })); - }); - - it("0.6 Assert values from getData() _assetStaked", async () => { - marketData = await marketInstance.getData(); - assert.equal(parseFloat(web3.utils.fromWei(marketData._ethStaked[0])).toFixed(1), (3).toFixed(1)); - assert.equal(parseFloat(web3.utils.fromWei(marketData._ethStaked[1])).toFixed(1), (3).toFixed(1)); - assert.equal(parseFloat(web3.utils.fromWei(marketData._ethStaked[2])).toFixed(1), (4).toFixed(1)); - }); - - it("1.0 prediction Points allocated properly in ether", async () => { - accounts = [user1, user2, user3, user4, user5, user6, user7, user8, user9, user10]; - options = [2, 2, 2, 3, 1, 1, 2, 3, 3, 2]; - getPredictionPoints = async (user, option, expected) => { - // return prediction points of user - let PredictionPoins = await marketInstance.getUserPredictionPoints(user, option); - PredictionPoins = PredictionPoins / 1; - return PredictionPoins; - }; - PredictionPointsExpected = [ - 1.755503471, - 83.41726908, - 11.21889102, - 306.0687072, - 510.3446361, - 1882.790363, - 116.4917104, - 634.1329064, - 36.98149537, - 721.7363059, - ]; - - for (let index = 0; index < 10; index++) { - let PredictionPoints = await getPredictionPoints(accounts[index], options[index]); - PredictionPoints = PredictionPoints / 1000; - PredictionPoints = PredictionPoints.toFixed(1); - await assert(PredictionPoints === PredictionPointsExpected[index].toFixed(1)); - } - }); - - it("1.1 Assert values from getData() prediction status before", async () => { - marketData = await marketInstance.getData(); - assert.equal(parseFloat(marketData._predictionStatus), 0); - }); - - it("1.2 Should not close market if time is not reached", async() => { - await marketInstance.settleMarket(); - marketData = await marketInstance.getData(); - assert.equal(parseFloat(marketData._predictionStatus), 0); - }); - - it("1.3 Should not close market if closing value is zero", async () => { - let MockchainLinkInstance = await MockchainLinkBTC.deployed(); - await MockchainLinkInstance.setLatestAnswer(1); - await increaseTime(36001); - await assertRevert(marketInstance.calculatePredictionResult(0)); - await MockchainLinkInstance.setLatestAnswer("10000000000000000000"); - await MockchainLinkInstance.setLatestAnswer("10000000000000000000"); - }); - - it("1.3", async () => { - await marketInstance.settleMarket(); - }); - - it("Cannot place prediction after prediction time", async ()=> { - await assertRevert(marketInstance.placePrediction("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", "1000000000", 2, 4, { - value: "1000000000", - from: user10 - })); - }); - - it("Raise dispute and reject", async() => { - await plotusToken.transfer(user11, "700000000000000000000"); - await plotusToken.approve(tokenController.address, "500000000000000000000", { - from: user11, - }); - let proposalId = await governance.getProposalLength(); - let marketETHBalanceBeforeDispute = await web3.eth.getBalance(marketInstance.address); - let registryBalanceBeforeDispute = await web3.eth.getBalance(plotusNewInstance.address); - await marketInstance.raiseDispute("500000000000000000000","","","", {from: user11}); - await increaseTime(604810); - await governance.closeProposal(proposalId/1); - let balanceAfterClosingDispute = await web3.eth.getBalance(marketInstance.address); - assert.equal(marketETHBalanceBeforeDispute/1, balanceAfterClosingDispute/1); - }); - - it("1.3 Assert values from getData() prediction status after", async () => { - marketData = await marketInstance.getData(); - assert.equal(parseFloat(marketData._predictionStatus), 4); - }); - it("1.4", async () => { - // plotus contract balance eth balance - plotusBalanceBefore = web3.utils.fromWei(await web3.eth.getBalance(plotusNewAddress)); - lotBalanceBefore = await plotusToken.balanceOf(openMarkets["_openMarkets"][0]); - assert.equal(parseFloat(plotusBalanceBefore).toFixed(3), (0.010).toFixed(3)); - assert.equal(parseFloat(web3.utils.fromWei(lotBalanceBefore)).toFixed(2), (832.5835).toFixed(2)); - await MockUniswapRouterInstance.setPrice("1000000000000000"); - await marketConfig.setPrice("1000000000000000"); - await increaseTime(360001); - - plotusBalanceAfter = web3.utils.fromWei(await web3.eth.getBalance(plotusNewAddress)); - assert.equal(parseFloat(plotusBalanceAfter).toFixed(3), (0.010).toFixed(3)); - lotBalanceAfter = await plotusToken.balanceOf(openMarkets["_openMarkets"][0]); - assert.equal(parseFloat(web3.utils.fromWei(lotBalanceAfter)).toFixed(2), (832.5835).toFixed(2)); - assert.equal( - parseFloat(web3.utils.fromWei(String(parseFloat(lotBalanceAfter) - parseFloat(lotBalanceBefore)))).toFixed(2), - (0).toFixed(2) - ); - }); - - it("2.check total return for each user prediction values in eth", async () => { - accounts = [user1, user2, user3, user4, user5, user6, user7, user8, user9, user10]; - options = [2, 2, 2, 3, 1, 1, 2, 3, 3, 2]; - getReturnsInEth = async (user) => { - // return userReturn in eth - const response = await marketInstance.getReturn(user); - let returnAmountInEth = web3.utils.fromWei(response[0][1]); - return returnAmountInEth; - }; - - const returnInEthExpected = [0, 0, 0, 0, 1.851161356, 5.141838644, 0.5994, 1.1988, 0.7992, 0.3996]; - // calulate rewards for every user in eth - - for (let index = 0; index < 10; index++) { - // check eth returns - let returns = await getReturnsInEth(accounts[index]); - assert.equal(parseFloat(returns).toFixed(2), returnInEthExpected[index].toFixed(2)); - } - }); - it("3.Check User Recived The appropriate amount", async () => { - accounts = [user1, user2, user3, user4, user5, user6, user7, user8, user9, user10]; - const totalReturnLotExpexted = [79.96, 239.88, 125.937, 49.1754, 72.00104504, 265.630055, 0, 0, 0, 0]; - const returnInEthExpected = [0, 0, 0, 0, 1.851161356, 5.141838644, 0.5994, 1.1988, 0.7992, 0.3996]; - - for (let account of accounts) { - beforeClaim = await web3.eth.getBalance(account); - beforeClaimToken = await plotusToken.balanceOf(account); - await marketInstance.claimReturn(account); - afterClaim = await web3.eth.getBalance(account); - afterClaimToken = await plotusToken.balanceOf(account); - diff = afterClaim - beforeClaim; - diff = new BigNumber(diff); - conv = new BigNumber(1000000000000000000); - diff = diff / conv; - diff = diff.toFixed(2); - expectedInEth = returnInEthExpected[accounts.indexOf(account)].toFixed(2); - assert.equal(diff*1, expectedInEth*1); - - diffToken = afterClaimToken - beforeClaimToken; - diffToken = diffToken / conv; - diffToken = diffToken.toFixed(1); - expectedInLot = totalReturnLotExpexted[accounts.indexOf(account)].toFixed(1); - assert.equal(diffToken, expectedInLot); - } - }); - // it("4. Market should have 0 balance after all claims", async () => { - // // console.log("Market Balance after claim" + (await web3.eth.getBalance(marketInstance.address)) / 1); - // assert.equal(parseFloat(await web3.eth.getBalance(marketInstance.address)), 0, "Market Balance must be 0 after all claims"); - // }); - it("5. Option price must be 0 after expire time", async () => { - await marketConfig.setMockPriceFlag(false); - let marketData = await marketInstance.getData(); - let optionPrice1 = parseFloat(marketData._optionPrice[0]); - let optionPrice2 = parseFloat(marketData._optionPrice[1]); - let optionPrice3 = parseFloat(marketData._optionPrice[2]); - assert.equal(optionPrice1, 0); - assert.equal(optionPrice2, 0); - assert.equal(optionPrice3, 0); - }); - }); -}); diff --git a/test/10_plotusMetaTx.js b/test/10_plotusMetaTx.js new file mode 100644 index 000000000..df386fe57 --- /dev/null +++ b/test/10_plotusMetaTx.js @@ -0,0 +1,517 @@ +const { assert } = require("chai"); + +const OwnedUpgradeabilityProxy = artifacts.require("OwnedUpgradeabilityProxy"); +const Master = artifacts.require("Master"); +const MarketConfig = artifacts.require("MockConfig"); +const PlotusToken = artifacts.require("MockPLOT"); +const Governance = artifacts.require("Governance"); +const ProposalCategory = artifacts.require("ProposalCategory"); +const TokenController = artifacts.require("TokenController"); +const BLOT = artifacts.require("BLOT"); +const AllMarkets = artifacts.require("MockAllMarkets"); +const MarketUtility = artifacts.require("MockConfig"); //mock +const MemberRoles = artifacts.require("MemberRoles"); +const MarketCreationRewards = artifacts.require('MarketCreationRewards'); +const BigNumber = require("bignumber.js"); +const { increaseTimeTo } = require("./utils/increaseTime.js"); +const encode1 = require('./utils/encoder.js').encode1; +const encode3 = require("./utils/encoder.js").encode3; +const signAndExecuteMetaTx = require("./utils/signAndExecuteMetaTx.js").signAndExecuteMetaTx; +const BN = require('bn.js'); + +const assertRevert = require("./utils/assertRevert.js").assertRevert; +const increaseTime = require("./utils/increaseTime.js").increaseTime; +const latestTime = require("./utils/latestTime.js").latestTime; +const encode = require("./utils/encoder.js").encode; +const gvProposal = require("./utils/gvProposal.js").gvProposalWithIncentiveViaTokenHolder; +const { toHex, toWei, toChecksumAddress } = require("./utils/ethTools"); +// get etherum accounts +// swap ether with LOT +let timeNow, + marketData, + expireTme, + priceOption1, + priceOption2, + priceOption3, + option1RangeMIN, + option1RangeMAX, + option2RangeMIN, + option2RangeMAX, + option3RangeMIX, + marketStatus, + option3RangeMAX, governance, + marketETHBalanceBeforeDispute, + marketIncentives; + +let privateKeyList = ["fb437e3e01939d9d4fef43138249f23dc1d0852e69b0b5d1647c087f869fabbd","7c85a1f1da3120c941b83d71a154199ee763307683f206b98ad92c3b4e0af13e","ecc9b35bf13bd5459350da564646d05c5664a7476fe5acdf1305440f88ed784c","f4470c3fca4dbef1b2488d016fae25978effc586a1f83cb29ac8cb6ab5bc2d50","141319b1a84827e1046e93741bf8a9a15a916d49684ab04925ac4ce4573eea23","d54b606094287758dcf19064a8d91c727346aadaa9388732e73c4315b7c606f9","49030e42ce4152e715a7ddaa10e592f8e61d00f70ef11f48546711f159d985df","b96761b1e7ebd1e8464a78a98fe52f53ce6035c32b4b2b12307a629a551ff7cf","d4786e2581571c863c7d12231c3afb6d4cef390c0ac9a24b243293721d28ea95","ed28e3d3530544f1cf2b43d1956b7bd13b63c612d963a8fb37387aa1a5e11460","05b127365cf115d4978a7997ee98f9b48f0ddc552b981c18aa2ee1b3e6df42c6","9d11dd6843f298b01b34bd7f7e4b1037489871531d14b58199b7cba1ac0841e6","f79e90fa4091de4fc2ec70f5bf67b24393285c112658e0d810e6bd711387fbb9","99f1fc0f09230ce745b6a256ba7082e6e51a2907abda3d9e735a5c8188bb4ba1","477f86cce983b9c91a36fdcd4a7ce21144a08dee9b1aafb91b9c70e57f717ce6","b03d2e6bb4a7d71c66a66ff9e9c93549cae4b593f634a4ea2a1f79f94200f5b4","9ddc0f53a81e631dcf39d5155f41ec12ed551b731efc3224f410667ba07b37dc","cf087ff9ae7c9954ad8612d071e5cdf34a6024ee1ae477217639e63a802a53dd","b64f62b94babb82cc78d3d1308631ae221552bb595202fc1d267e1c29ce7ba60","a91e24875f8a534497459e5ccb872c4438be3130d8d74b7e1104c5f94cdcf8c2","4f49f3d029eeeb3fed14d59625acd088b6b34f3b41c527afa09d29e4a7725c32","179795fd7ac7e7efcba3c36d539a1e8659fb40d77d0a3fab2c25562d99793086","4ba37d0b40b879eceaaca2802a1635f2e6d86d5c31e3ff2d2fd13e68dd2a6d3d","6b7f5dfba9cd3108f1410b56f6a84188eee23ab48a3621b209a67eea64293394","870c540da9fafde331a3316cee50c17ad76ddb9160b78b317bef2e6f6fc4bac0","470b4cccaea895d8a5820aed088357e380d66b8e7510f0a1ea9b575850160241","8a55f8942af0aec1e0df3ab328b974a7888ffd60ded48cc6862013da0f41afbc","2e51e8409f28baf93e665df2a9d646a1bf9ac8703cbf9a6766cfdefa249d5780","99ef1a23e95910287d39493d8d9d7d1f0b498286f2b1fdbc0b01495f10cf0958","6652200c53a4551efe2a7541072d817562812003f9d9ef0ec17995aa232378f8","39c6c01194df72dda97da2072335c38231ced9b39afa280452afcca901e73643","12097e411d948f77b7b6fa4656c6573481c1b4e2864c1fca9d5b296096707c45","cbe53bf1976aee6cec830a848c6ac132def1503cffde82ccfe5bd15e75cbaa72","eeab5dcfff92dbabb7e285445aba47bd5135a4a3502df59ac546847aeb5a964f","5ea8279a578027abefab9c17cef186cccf000306685e5f2ee78bdf62cae568dd","0607767d89ad9c7686dbb01b37248290b2fa7364b2bf37d86afd51b88756fe66","e4fd5f45c08b52dae40f4cdff45e8681e76b5af5761356c4caed4ca750dc65cd","145b1c82caa2a6d703108444a5cf03e9cb8c3cd3f19299582a564276dbbba734","736b22ec91ae9b4b2b15e8d8c220f6c152d4f2228f6d46c16e6a9b98b4733120","ac776cb8b40f92cdd307b16b83e18eeb1fbaa5b5d6bd992b3fda0b4d6de8524c","65ba30e2202fdf6f37da0f7cfe31dfb5308c9209885aaf4cef4d572fd14e2903","54e8389455ec2252de063e83d3ce72529d674e6d2dc2070661f01d4f76b63475","fbbbfb525dd0255ee332d51f59648265aaa20c2e9eff007765cf4d4a6940a849","8de5e418f34d04f6ea947ce31852092a24a705862e6b810ca9f83c2d5f9cda4d","ea6040989964f012fd3a92a3170891f5f155430b8bbfa4976cde8d11513b62d9","14d94547b5deca767137fbd14dae73e888f3516c742fad18b83be333b38f0b88","47f05203f6368d56158cda2e79167777fc9dcb0c671ef3aabc205a1636c26a29"]; + + +contract("Rewards-Market", async function(users) { + describe("Scenario1", async () => { + it("0.0", async () => { + masterInstance = await OwnedUpgradeabilityProxy.deployed(); + masterInstance = await Master.at(masterInstance.address); + plotusToken = await PlotusToken.deployed(); + BLOTInstance = await BLOT.deployed(); + tokenController =await TokenController.at(await masterInstance.getLatestAddress(web3.utils.toHex("TC"))); + governance = await masterInstance.getLatestAddress(web3.utils.toHex("GV")); + governance = await Governance.at(governance); + marketConfig = await masterInstance.getLatestAddress(web3.utils.toHex("MU")); + marketConfig = await MarketConfig.at(marketConfig); + timeNow = await latestTime(); + + allMarkets = await AllMarkets.at(await masterInstance.getLatestAddress(web3.utils.toHex("AM"))); + marketIncentives = await MarketCreationRewards.at(await masterInstance.getLatestAddress(web3.utils.toHex("MC"))); + await increaseTime(5 * 3600); + await plotusToken.transfer(users[12],toWei(100000)); + await plotusToken.transfer(users[11],toWei(100000)); + await plotusToken.transfer(marketIncentives.address,toWei(500)); + await plotusToken.approve(tokenController.address,toWei(200000),{from:users[11]}); + await tokenController.lock(toHex("SM"),toWei(100000),30*3600*24,{from:users[11]}); + + let nullAddress = "0x0000000000000000000000000000"; + + await plotusToken.transfer(users[11],toWei(100)); + await plotusToken.approve(allMarkets.address,toWei(200000),{from:users[11]}); + await marketConfig.setNextOptionPrice(18); + await allMarkets.claimRelayerRewards(); + await allMarkets.createMarket(0, 0,{from:users[11],gasPrice:500000}); + // await marketIncentives.claimCreationReward(100,{from:users[11]}); + }); + + it("Scenario 1: Few user wins", async () => { + let i; + let totalDepositedPlot = toWei(1000); + let predictionVal = [0,100, 400, 210, 123, 500, 700, 200, 50, 300, 150]; + let options=[0,2,2,2,3,1,1,2,3,3,2,1]; + let daoCommissions = [0, 1.8, 6.4, 3.36, 1.968, 8, 11.2, 3.2, 0.8, 4.8, 2.4]; + for(i=1; i<11;i++){ + if(i>1) { + await allMarkets.setReferrer(users[1], users[i]); + //SHould not add referrer if already set + await assertRevert(allMarkets.setReferrer(users[1], users[i])); + } + await plotusToken.transfer(users[i], toWei(2000)); + await plotusToken.approve(allMarkets.address, toWei(1000000), { from: users[i] }); + let functionSignature = encode3("depositAndPlacePrediction(uint,uint,address,uint64,uint256)", totalDepositedPlot, 7, plotusToken.address, predictionVal[i]*1e8, options[i]); + await marketConfig.setNextOptionPrice(options[i]*9); + let daoBalanceBefore = await plotusToken.balanceOf(marketIncentives.address); + // await allMarkets.depositAndPlacePrediction(totalDepositedPlot, 7, plotusToken.address, predictionVal[i]*1e8, options[i]); + await signAndExecuteMetaTx( + privateKeyList[i], + users[i], + functionSignature, + allMarkets, + "AM" + ); + let daoBalanceAfter = await plotusToken.balanceOf(marketIncentives.address); + assert.equal(daoBalanceAfter - daoBalanceBefore, daoCommissions[i]*1e18); + } + + //SHould not add referrer if already placed prediction + await assertRevert(allMarkets.setReferrer(users[1], users[2])); + let relayerBalBefore = await plotusToken.balanceOf(users[0]); + await allMarkets.claimRelayerRewards(); + let relayerBalAfter = await plotusToken.balanceOf(users[0]); + + assert.equal(Math.round((relayerBalAfter-relayerBalBefore)/1e15),5.466*1e3); + + + let betpoints = [0,5444.44444, 21777.77777, 11433.33333, 4464.44444, 54444.44444, 76222.22222, 10888.88888, 1814.81481, 10888.88888, 8166.66666, 1814.81481, 1814.81481, 1814.81481]; + + + for(i=1;i<=11;i++) + { + let betPointUser = (await allMarkets.getUserPredictionPoints(users[i],7,options[i]))/1e5; + if(i == 11) { + let betPointUser1 = (await allMarkets.getUserPredictionPoints(users[i],7,2))/1e5; + assert.equal(betPointUser1,betpoints[i+1]); + let betPointUser2 = (await allMarkets.getUserPredictionPoints(users[i],7,3))/1e5; + assert.equal(betPointUser2,betpoints[i+1]); + } + assert.equal(betPointUser,betpoints[i]); + let unusedBal = await allMarkets.getUserUnusedBalance(users[i]); + if(i != 11) + assert.equal(totalDepositedPlot/1e18-unusedBal[0]/1e18,predictionVal[i]); + } + + await increaseTime(8*60*60); + + await allMarkets.postResultMock(1,7); + await plotusToken.transfer(users[12], "700000000000000000000"); + await plotusToken.approve(allMarkets.address, "500000000000000000000", { + from: users[12], + }); + let proposalId = await governance.getProposalLength(); + await allMarkets.raiseDispute(7, "500000000000000000000","","","", {from: users[12]}); + await increaseTime(604810); + await governance.closeProposal(proposalId/1); + + await increaseTime(60*61); + + let userRewardPlot = [0,0,0,0,0,1118.14308219,1565.400315,0,0,0,0]; + for(i=1;i<11;i++) + { + let reward = await allMarkets.getReturn(users[i],7); + // assert.equal(Math.round(reward/1e2),userRewardPlot[i]*1e6); + let plotBalBefore = await plotusToken.balanceOf(users[i]); + let plotEthUnused = await allMarkets.getUserUnusedBalance(users[i]); + functionSignature = encode3("withdraw(uint,uint)", plotEthUnused[0].iadd(plotEthUnused[1]), 100); + await signAndExecuteMetaTx( + privateKeyList[i], + users[i], + functionSignature, + allMarkets, + "AM" + ); + let plotBalAfter = await plotusToken.balanceOf(users[i]); + assert.equal(Math.round((plotBalAfter-plotBalBefore)/1e18),Math.round((totalDepositedPlot/1e18-predictionVal[i])/1+reward/1e8)); + } + + let marketCreatorReward = await marketIncentives.getPendingMarketCreationRewards(users[11]); + assert.equal(391918333,Math.round(marketCreatorReward[1]/1e11)); + + let plotBalBeforeCreator = await plotusToken.balanceOf(users[11]); + + functionSignature = encode3("claimCreationReward(uint256)", 100); + await signAndExecuteMetaTx( + privateKeyList[11], + users[11], + functionSignature, + marketIncentives, + "MC" + ); + + let plotBalAfterCreator = await plotusToken.balanceOf(users[11]); + + assert.equal(Math.round((plotBalAfterCreator-plotBalBeforeCreator)/1e11),391918333); + + + }); + + it("Check referral fee", async () => { + let referralRewardPlot = [2.633, 0.4, 0.21, 0.123, 0.5, 0.7, 0.2, 0.05, 0.3, 0.15]; + + for(i=1;i<11;i++) + { + let reward = await allMarkets.getReferralFees(users[i]); + if(i == 1) { + reward = reward[0]; + } else { + reward = reward[1]; + } + assert.equal(reward/1,referralRewardPlot[i-1]*1e8); + let plotBalBefore = await plotusToken.balanceOf(users[i]); + functionSignature = encode3("claimReferralFee(address)", users[i]); + await signAndExecuteMetaTx( + privateKeyList[i], + users[i], + functionSignature, + allMarkets, + "AM" + ); + let plotBalAfter = await plotusToken.balanceOf(users[i]); + assert.equal(Math.round((plotBalAfter/1e13-plotBalBefore/1e13)),reward/1e3); + } + }) + }); +}); + +contract("Rewards-Market Stake less than 1 ether", async function(users) { + describe("Scenario1", async () => { + it("0.0", async () => { + masterInstance = await OwnedUpgradeabilityProxy.deployed(); + masterInstance = await Master.at(masterInstance.address); + plotusToken = await PlotusToken.deployed(); + BLOTInstance = await BLOT.deployed(); + tokenController =await TokenController.at(await masterInstance.getLatestAddress(web3.utils.toHex("TC"))); + governance = await masterInstance.getLatestAddress(web3.utils.toHex("GV")); + governance = await Governance.at(governance); + marketConfig = await masterInstance.getLatestAddress(web3.utils.toHex("MU")); + marketConfig = await MarketConfig.at(marketConfig); + timeNow = await latestTime(); + + allMarkets = await AllMarkets.at(await masterInstance.getLatestAddress(web3.utils.toHex("AM"))); + marketIncentives = await MarketCreationRewards.at(await masterInstance.getLatestAddress(web3.utils.toHex("MC"))); + await increaseTime(5 * 3600); + await plotusToken.transfer(users[12],toWei(100000)); + await plotusToken.transfer(users[11],toWei(100000)); + await plotusToken.transfer(marketIncentives.address,toWei(500)); + await plotusToken.approve(tokenController.address,toWei(200000),{from:users[11]}); + await tokenController.lock(toHex("SM"),toWei(100000),30*3600*24,{from:users[11]}); + + let nullAddress = "0x0000000000000000000000000000"; + + await plotusToken.transfer(users[11],toWei(100)); + await plotusToken.approve(allMarkets.address,toWei(200000),{from:users[11]}); + await marketConfig.setNextOptionPrice(18); + await allMarkets.claimRelayerRewards(); + await allMarkets.createMarket(0, 0,{from:users[11],gasPrice:500000}); + // await marketIncentives.claimCreationReward(100,{from:users[11]}); + }); + + it("Scenario 1: Few user wins", async () => { + let i; + let totalDepositedPlot = toWei(100); + let predictionVal = [100]; + let options=[1, 2, 3]; + + let relayerBalBefore = await plotusToken.balanceOf(users[0]); + await assertRevert(allMarkets.claimRelayerRewards()); + let relayerBalAfter = await plotusToken.balanceOf(users[0]); + + assert.equal(((relayerBalAfter-relayerBalBefore)/1e18),0); + + relayerBalBefore = await plotusToken.balanceOf(users[11]); + await allMarkets.claimRelayerRewards({from:users[11]}); + relayerBalAfter = await plotusToken.balanceOf(users[11]); + + assert.equal(((relayerBalAfter-relayerBalBefore)/1e18),0.19999998); + + + let betpoints = [1814.81481, 1814.81481, 1814.81481]; + + + for(i=0;i<3;i++) + { + let betPointUser = (await allMarkets.getUserPredictionPoints(users[11],7,options[i]))/1e5; + assert.equal(betPointUser,betpoints[i]); + } + let unusedBal = await allMarkets.getUserUnusedBalance(users[11]); + assert.equal(totalDepositedPlot/1e18-unusedBal[0]/1e18,99.99999999); + + await increaseTime(8*60*60); + + await allMarkets.postResultMock(1,7); + await plotusToken.transfer(users[12], "700000000000000000000"); + await plotusToken.approve(allMarkets.address, "500000000000000000000", { + from: users[12], + }); + + await increaseTime(2*60*61); + + let reward = await allMarkets.getReturn(users[11],7); + // assert.equal(Math.round(reward/1e2),userRewardPlot[i]*1e6); + let plotBalBefore = await plotusToken.balanceOf(users[11]); + let plotEthUnused = await allMarkets.getUserUnusedBalance(users[11]); + functionSignature = encode3("withdraw(uint,uint)", plotEthUnused[0].iadd(plotEthUnused[1]), 100); + await signAndExecuteMetaTx( + privateKeyList[11], + users[11], + functionSignature, + allMarkets, + "AM" + ); + let plotBalAfter = await plotusToken.balanceOf(users[11]); + assert.equal(Math.round((plotBalAfter-plotBalBefore)/1e18),Math.round(reward/1e8)); + let marketCreatorReward = await marketIncentives.getPendingMarketCreationRewards(users[11]); + assert.equal(0,Math.round(marketCreatorReward[1]/1e11)); + + let plotBalBeforeCreator = await plotusToken.balanceOf(users[11]); + + functionSignature = encode3("claimCreationReward(uint256)", 100); + await assertRevert(signAndExecuteMetaTx( + privateKeyList[11], + users[11], + functionSignature, + marketIncentives, + "MC" + )); + + let plotBalAfterCreator = await plotusToken.balanceOf(users[11]); + + assert.equal(Math.round((plotBalAfterCreator-plotBalBeforeCreator)/1e11),0); + + + }); + + }); +}); + +contract("Rewards-Market Raise dispute and pass the proposal ", async function(users) { + describe("Scenario1", async () => { + it("0.0", async () => { + masterInstance = await OwnedUpgradeabilityProxy.deployed(); + masterInstance = await Master.at(masterInstance.address); + plotusToken = await PlotusToken.deployed(); + BLOTInstance = await BLOT.deployed(); + tokenController =await TokenController.at(await masterInstance.getLatestAddress(web3.utils.toHex("TC"))); + governance = await masterInstance.getLatestAddress(web3.utils.toHex("GV")); + governance = await Governance.at(governance); + marketConfig = await masterInstance.getLatestAddress(web3.utils.toHex("MU")); + marketConfig = await MarketConfig.at(marketConfig); + timeNow = await latestTime(); + + allMarkets = await AllMarkets.at(await masterInstance.getLatestAddress(web3.utils.toHex("AM"))); + marketIncentives = await MarketCreationRewards.at(await masterInstance.getLatestAddress(web3.utils.toHex("MC"))); + await increaseTime(5 * 3600); + await plotusToken.transfer(users[12],toWei(100000)); + await plotusToken.transfer(users[11],toWei(100000)); + await plotusToken.transfer(marketIncentives.address,toWei(500)); + await plotusToken.approve(tokenController.address,toWei(200000),{from:users[11]}); + await tokenController.lock(toHex("SM"),toWei(100000),30*3600*24,{from:users[11]}); + + let nullAddress = "0x0000000000000000000000000000"; + + await plotusToken.transfer(users[11],toWei(100)); + await plotusToken.approve(allMarkets.address,toWei(200000),{from:users[11]}); + await marketConfig.setNextOptionPrice(18); + await allMarkets.claimRelayerRewards(); + await allMarkets.createMarket(0, 0,{from:users[11],gasPrice:500000}); + // await marketIncentives.claimCreationReward(100,{from:users[11]}); + }); + + it("Scenario 1: Few user wins", async () => { + let i; + let totalDepositedPlot = toWei(1000); + let predictionVal = [0,100, 400, 210, 123, 500, 700, 200, 50, 300, 150]; + let options=[0,2,2,2,3,1,1,2,3,3,2,1]; + let daoCommissions = [0, 1.8, 6.4, 3.36, 1.968, 8, 11.2, 3.2, 0.8, 4.8, 2.4]; + for(i=1; i<11;i++){ + if(i>1) { + await allMarkets.setReferrer(users[1], users[i]); + //SHould not add referrer if already set + await assertRevert(allMarkets.setReferrer(users[1], users[i])); + } + await plotusToken.transfer(users[i], toWei(2000)); + await plotusToken.approve(allMarkets.address, toWei(1000000), { from: users[i] }); + let functionSignature = encode3("depositAndPlacePrediction(uint,uint,address,uint64,uint256)", totalDepositedPlot, 7, plotusToken.address, predictionVal[i]*1e8, options[i]); + await marketConfig.setNextOptionPrice(options[i]*9); + let daoBalanceBefore = await plotusToken.balanceOf(marketIncentives.address); + // await allMarkets.depositAndPlacePrediction(totalDepositedPlot, 7, plotusToken.address, predictionVal[i]*1e8, options[i]); + await signAndExecuteMetaTx( + privateKeyList[i], + users[i], + functionSignature, + allMarkets, + "AM" + ); + let daoBalanceAfter = await plotusToken.balanceOf(marketIncentives.address); + assert.equal(daoBalanceAfter - daoBalanceBefore, daoCommissions[i]*1e18); + } + + //SHould not add referrer if already placed prediction + await assertRevert(allMarkets.setReferrer(users[1], users[2])); + let relayerBalBefore = await plotusToken.balanceOf(users[0]); + await allMarkets.claimRelayerRewards(); + let relayerBalAfter = await plotusToken.balanceOf(users[0]); + + assert.equal(Math.round((relayerBalAfter-relayerBalBefore)/1e15),5.466*1e3); + + + let betpoints = [0,5444.44444, 21777.77777, 11433.33333, 4464.44444, 54444.44444, 76222.22222, 10888.88888, 1814.81481, 10888.88888, 8166.66666, 1814.81481, 1814.81481, 1814.81481]; + + + for(i=1;i<=11;i++) + { + let betPointUser = (await allMarkets.getUserPredictionPoints(users[i],7,options[i]))/1e5; + if(i == 11) { + let betPointUser1 = (await allMarkets.getUserPredictionPoints(users[i],7,2))/1e5; + assert.equal(betPointUser1,betpoints[i+1]); + let betPointUser2 = (await allMarkets.getUserPredictionPoints(users[i],7,3))/1e5; + assert.equal(betPointUser2,betpoints[i+1]); + } + assert.equal(betPointUser,betpoints[i]); + let unusedBal = await allMarkets.getUserUnusedBalance(users[i]); + if(i != 11) + assert.equal(totalDepositedPlot/1e18-unusedBal[0]/1e18,predictionVal[i]); + } + + await increaseTime(8*60*60); + + await allMarkets.postResultMock(1,7); + await plotusToken.transfer(users[12], "700000000000000000000"); + await plotusToken.approve(allMarkets.address, "500000000000000000000", { + from: users[12], + }); + let proposalId = await governance.getProposalLength(); + await allMarkets.raiseDispute(7, "500000000000000000000","","","", {from: users[12]}); + await plotusToken.transfer(users[13], "20000000000000000000000"); + await plotusToken.transfer(users[14], "20000000000000000000000"); + await plotusToken.transfer(users[15], "20000000000000000000000"); + await plotusToken.approve(tokenController.address, "20000000000000000000000",{from : users[13]}); + await tokenController.lock("0x4452","20000000000000000000000",(86400*20),{from : users[13]}); + + await plotusToken.approve(tokenController.address, "20000000000000000000000",{from : users[14]}); + await tokenController.lock("0x4452","20000000000000000000000",(86400*20),{from : users[14]}); + + + await plotusToken.approve(tokenController.address, "20000000000000000000000",{from : users[15]}); + await tokenController.lock("0x4452","20000000000000000000000",(86400*20),{from : users[15]}); + + await governance.submitVote(proposalId, 1, {from:users[13]}); + await governance.submitVote(proposalId, 1, {from:users[14]}); + await governance.submitVote(proposalId, 1, {from:users[15]}); + await increaseTime(604800); + await governance.closeProposal(proposalId/1); + + await increaseTime(60*61); + assert.equal((await allMarkets.getMarketResults(7))[0]/1, 3); + + let userRewardPlot = [0, 0, 0, 0, 195.4564356, 0, 0, 0, 79.45383562, 476.7230137, 0]; + for(i=1;i<11;i++) + { + let reward = await allMarkets.getReturn(users[i],7); + // assert.equal(Math.round(reward/1e2),userRewardPlot[i]*1e6); + let plotBalBefore = await plotusToken.balanceOf(users[i]); + let plotEthUnused = await allMarkets.getUserUnusedBalance(users[i]); + functionSignature = encode3("withdraw(uint,uint)", plotEthUnused[0].iadd(plotEthUnused[1]), 100); + await signAndExecuteMetaTx( + privateKeyList[i], + users[i], + functionSignature, + allMarkets, + "AM" + ); + let plotBalAfter = await plotusToken.balanceOf(users[i]); + assert.equal(Math.round((plotBalAfter-plotBalBefore)/1e18),Math.round((totalDepositedPlot/1e18-predictionVal[i])/1+reward/1e8)); + } + + let marketCreatorReward = await marketIncentives.getPendingMarketCreationRewards(users[11]); + assert.equal(570033333,Math.round(marketCreatorReward[1]/1e11)); + + let plotBalBeforeCreator = await plotusToken.balanceOf(users[11]); + + functionSignature = encode3("claimCreationReward(uint256)", 100); + await signAndExecuteMetaTx( + privateKeyList[11], + users[11], + functionSignature, + marketIncentives, + "MC" + ); + + let plotBalAfterCreator = await plotusToken.balanceOf(users[11]); + + assert.equal(Math.round((plotBalAfterCreator-plotBalBeforeCreator)/1e11),570033333); + + + }); + + it("Check referral fee", async () => { + let referralRewardPlot = [2.633, 0.4, 0.21, 0.123, 0.5, 0.7, 0.2, 0.05, 0.3, 0.15]; + + for(i=1;i<11;i++) + { + let reward = await allMarkets.getReferralFees(users[i]); + if(i == 1) { + reward = reward[0]; + } else { + reward = reward[1]; + } + assert.equal(reward/1,referralRewardPlot[i-1]*1e8); + let plotBalBefore = await plotusToken.balanceOf(users[i]); + functionSignature = encode3("claimReferralFee(address)", users[i]); + await signAndExecuteMetaTx( + privateKeyList[i], + users[i], + functionSignature, + allMarkets, + "AM" + ); + let plotBalAfter = await plotusToken.balanceOf(users[i]); + assert.equal(Math.round((plotBalAfter/1e13-plotBalBefore/1e13)),reward/1e3); + } + }) + }); +}); diff --git a/test/11_plotus2.js b/test/11_plotus2.js deleted file mode 100644 index 4540fecac..000000000 --- a/test/11_plotus2.js +++ /dev/null @@ -1,487 +0,0 @@ -const { assert } = require("chai"); -const OwnedUpgradeabilityProxy = artifacts.require("OwnedUpgradeabilityProxy"); -const Market = artifacts.require("MockMarket"); -const Plotus = artifacts.require("MarketRegistry"); -const Master = artifacts.require("Master"); -const Governance = artifacts.require("Governance"); -const MemberRoles = artifacts.require("MockMemberRoles"); -const TokenController = artifacts.require("TokenController"); -const PlotusToken = artifacts.require("MockPLOT"); -const MarketConfig = artifacts.require("MockConfig"); -const BLOT = artifacts.require("BLOT"); -const MockUniswapRouter = artifacts.require("MockUniswapRouter"); -const BigNumber = require("bignumber.js"); - -const web3 = Market.web3; -const increaseTime = require("./utils/increaseTime.js").increaseTime; -// get etherum accounts -// swap ether with LOT - -contract("Market", async function([user1, user2, user3, user4, user5, user6, user7, user8, user9, user10]) { - it("Place the prediction with ether", async () => { - masterInstance = await OwnedUpgradeabilityProxy.deployed(); - masterInstance = await Master.at(masterInstance.address); - plotusToken = await PlotusToken.deployed(); - BLOTInstance = await BLOT.deployed(); - MockUniswapRouterInstance = await MockUniswapRouter.deployed(); - plotusNewAddress = await masterInstance.getLatestAddress(web3.utils.toHex("PL")); - tokenController =await TokenController.at(await masterInstance.getLatestAddress(web3.utils.toHex("TC"))); - plotusNewInstance = await Plotus.at(plotusNewAddress); - marketConfig = await plotusNewInstance.marketUtility(); - marketConfig = await MarketConfig.at(marketConfig); - // console.log(await plotusNewInstance.getOpenMarkets()); - openMarkets = await plotusNewInstance.getOpenMarkets(); - - // console.log(`OpenMaket : ${openMarkets["_openMarkets"][0]}`); - - marketInstance = await Market.at(openMarkets["_openMarkets"][0]); - await increaseTime(10001); - assert.ok(marketInstance); - - // setting option price in eth - await marketConfig.setOptionPrice(1, 9); - await marketConfig.setOptionPrice(2, 18); - await marketConfig.setOptionPrice(3, 27); - - // set price - // user 1 - // set price lot - await MockUniswapRouterInstance.setPrice("1000000000000000"); - await marketConfig.setPrice("1000000000000000"); - await plotusToken.approve(tokenController.address, "100000000000000000000", { - from: user1, - }); - await marketInstance.placePrediction(plotusToken.address, "100000000000000000000", 2, 1, { from: user1 }); - - // user 2 - await MockUniswapRouterInstance.setPrice("2000000000000000"); - await marketConfig.setPrice("2000000000000000"); - await plotusToken.transfer(user2, "500000000000000000000"); - - await plotusToken.approve(tokenController.address, "400000000000000000000", { - from: user2, - }); - await marketInstance.placePrediction(plotusToken.address, "400000000000000000000", 2, 2, { from: user2 }); - // user 3 - await MockUniswapRouterInstance.setPrice("1000000000000000"); - await marketConfig.setPrice("1000000000000000"); - await plotusToken.transfer(user3, "500000000000000000000"); - await plotusToken.approve(tokenController.address, "210000000000000000000", { - from: user3, - }); - await marketInstance.placePrediction(plotusToken.address, "210000000000000000000", 2, 2, { from: user3 }); - await MockUniswapRouterInstance.setPrice("15000000000000000"); - await marketConfig.setPrice("15000000000000000"); - - await plotusToken.transfer(user4, "200000000000000000000"); - - await plotusToken.approve(tokenController.address, "123000000000000000000", { - from: user4, - }); - await marketInstance.placePrediction(plotusToken.address, "123000000000000000000", 3, 3, { from: user4 }); - - // user 5 - await MockUniswapRouterInstance.setPrice("12000000000000000"); - await marketConfig.setPrice("12000000000000000"); - await marketInstance.placePrediction("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", "1000000000000000000", 2, 4, { - value: "1000000000000000000", - from: user5, - }); - - // user 6 - await MockUniswapRouterInstance.setPrice("14000000000000000"); - await marketConfig.setPrice("14000000000000000"); - await marketInstance.placePrediction("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", "2000000000000000000", 3, 5, { - value: "2000000000000000000", - from: user6, - }); - // user 7 - await MockUniswapRouterInstance.setPrice("10000000000000000"); - await marketConfig.setPrice("10000000000000000"); - - await marketInstance.placePrediction("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", "1000000000000000000", 2, 2, { - value: "1000000000000000000", - from: user7, - }); - // user 8 - await MockUniswapRouterInstance.setPrice("45000000000000000"); - await marketConfig.setPrice("45000000000000000"); - await marketInstance.placePrediction("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", "3000000000000000000", 3, 3, { - value: "3000000000000000000", - from: user8, - }); - // user 9 - await MockUniswapRouterInstance.setPrice("51000000000000000"); - await marketConfig.setPrice("51000000000000000"); - await marketInstance.placePrediction("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", "1000000000000000000", 3, 1, { - value: "1000000000000000000", - from: user9, - }); - // user 10 - await MockUniswapRouterInstance.setPrice("12000000000000000"); - await marketConfig.setPrice("12000000000000000"); - await marketInstance.placePrediction("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", "2000000000000000000", 2, 4, { - value: "2000000000000000000", - from: user10, - }); - }); - - it("1.0 Prediction Points allocated properly in ether", async () => { - accounts = [user1, user2, user3, user4, user5, user6, user7, user8, user9, user10]; - options = [2, 2, 2, 3, 2, 3, 2, 3, 3, 2]; - getpredictionPoints = async (user, option, expected) => { - // return Prediction points of user - let predictionPoints = await marketInstance.getUserPredictionPoints(user, option); - predictionPoints = predictionPoints / 1; - return predictionPoints; - }; - predictionPointsExpected = [ - 1.755503471, - 83.41726908, - 11.21889102, - 306.0687072, - 255.1723181, - 627.5967878, - 116.4917104, - 634.1329064, - 36.98149537, - 721.7363059, - ]; - - for (let index = 0; index < 10; index++) { - let PredictionPoints = await getpredictionPoints(accounts[index], options[index]); - PredictionPoints = PredictionPoints / 1000; - PredictionPoints = PredictionPoints.toFixed(1); - await assert.equal(PredictionPoints, predictionPointsExpected[index].toFixed(1)); - } - await increaseTime(36001); - await marketInstance.calculatePredictionResult(1); - await increaseTime(36001); - // plotus contract balance eth balance - - plotusBalanceBefore = web3.utils.fromWei(await web3.eth.getBalance(plotusNewAddress)); - lotBalanceBefore = await plotusToken.balanceOf(openMarkets["_openMarkets"][0]); - assert.equal(parseFloat(plotusBalanceBefore), (6.657336 + 0.145864).toFixed(5)); //stake-amount lost - assert.equal(parseFloat(web3.utils.fromWei(lotBalanceBefore)).toFixed(2), (494.95).toFixed(2)); - - await MockUniswapRouterInstance.setPrice("1000000000000000"); - await marketConfig.setPrice("1000000000000000"); - await increaseTime(360001); - - plotusBalanceAfter = await web3.eth.getBalance(plotusNewAddress); - lotBalanceAfter = await plotusToken.balanceOf(openMarkets["_openMarkets"][0]); - assert.equal(parseFloat(plotusBalanceAfter), web3.utils.toWei("6.8032")); - assert.equal(parseFloat(web3.utils.fromWei(lotBalanceAfter)).toFixed(2), (494.9524).toFixed(2)); - assert.equal(parseFloat(web3.utils.fromWei(String(parseFloat(lotBalanceAfter) - parseFloat(lotBalanceBefore)))).toFixed(2), (0).toFixed(2)); - }); - it("2.check total return for each user Prediction values in eth", async () => { - accounts = [user1, user2, user3, user4, user5, user6, user7, user8, user9, user10]; - options = [2, 2, 2, 3, 2, 3, 2, 3, 3, 2]; - getReturnsInEth = async (user) => { - // return userReturn in eth - const response = await marketInstance.getReturn(user); - let returnAmountInEth = web3.utils.fromWei(response[0][1]); - return returnAmountInEth; - }; - const returnInEthExpected = [0, 0, 0, 0, 0.1998, 0, 0.5994, 1.1988, 0.7992, 0.3996]; - // calulate rewards for every user in eth - for (let index = 0; index < 10; index++) { - // check eth returns - let returns = await getReturnsInEth(accounts[index]); - assert.equal(parseFloat(returns).toFixed(2), returnInEthExpected[index].toFixed(2)); - } - }); - it("3.Check User Recived The appropriate amount", async () => { - accounts = [user1, user2, user3, user4, user5, user6, user7, user8, user9, user10]; - const totalReturnLotExpexted = [79.96, 239.88, 125.937, 49.1754, 0, 0, 0, 0, 0, 0]; - const returnInEthExpected = [0, 0, 0, 0, 0.1998, 0, 0.5994, 1.1988, 0.7992, 0.3996]; - - for (let account of accounts) { - beforeClaim = await web3.eth.getBalance(account); - beforeClaimToken = await plotusToken.balanceOf(account); - await marketInstance.claimReturn(account); - afterClaim = await web3.eth.getBalance(account); - afterClaimToken = await plotusToken.balanceOf(account); - diff = afterClaim - beforeClaim; - diff = new BigNumber(diff); - conv = new BigNumber(1000000000000000000); - diff = diff / conv; - diff = diff.toFixed(2); - expectedInEth = returnInEthExpected[accounts.indexOf(account)].toFixed(2); - assert.equal(diff*1, expectedInEth*1); - - diffToken = afterClaimToken - beforeClaimToken; - diffToken = diffToken / conv; - diffToken = diffToken.toFixed(1); - expectedInLot = totalReturnLotExpexted[accounts.indexOf(account)].toFixed(1); - assert.equal(diffToken, expectedInLot); - } - // console.log((await web3.eth.getBalance(marketInstance.address)) / 1); - }); - // it("4. Market should have 0 balance after all claims", async () => { - // // console.log("Market Balance after claim" + (await web3.eth.getBalance(marketInstance.address)) / 1); - // assert.equal(parseFloat(await web3.eth.getBalance(marketInstance.address)), 0, "Market Balance must be 0 after all claims"); - // }); - it("5. Option price must be 0 after expire time", async () => { - await marketConfig.setMockPriceFlag(false); - let marketData = await marketInstance.getData(); - let optionPrice1 = parseFloat(marketData._optionPrice[0]); - let optionPrice2 = parseFloat(marketData._optionPrice[1]); - let optionPrice3 = parseFloat(marketData._optionPrice[2]); - assert.equal(optionPrice1, 0); - assert.equal(optionPrice2, 0); - assert.equal(optionPrice3, 0); - }); -}); - -contract("Raise Dispute and accpet the dispute", async function([user1, user2, user3, user4, user5, user6, user7, user8, user9, user10, user11, dr1, dr2, dr3]) { - it("Place the prediction", async () => { - masterInstance = await OwnedUpgradeabilityProxy.deployed(); - masterInstance = await Master.at(masterInstance.address); - plotusToken = await PlotusToken.deployed(); - BLOTInstance = await BLOT.deployed(); - MockUniswapRouterInstance = await MockUniswapRouter.deployed(); - plotusNewAddress = await masterInstance.getLatestAddress(web3.utils.toHex("PL")); - plotusNewInstance = await Plotus.at(plotusNewAddress); - marketConfig = await plotusNewInstance.marketUtility(); - marketConfig = await MarketConfig.at(marketConfig); - governance = await masterInstance.getLatestAddress(web3.utils.toHex("GV")); - governance = await Governance.at(governance); - let mr = await MemberRoles.at(await masterInstance.getLatestAddress(web3.utils.toHex("MR"))); - let tokenController = await TokenController.at(await masterInstance.getLatestAddress(web3.utils.toHex("TC"))); - await plotusToken.transfer(dr1, "20000000000000000000000"); - await plotusToken.transfer(dr2, "20000000000000000000000"); - await plotusToken.transfer(dr3, "20000000000000000000000"); - await plotusToken.approve(tokenController.address, "20000000000000000000000",{from : dr1}); - await tokenController.lock("0x4452","20000000000000000000000",(86400*20),{from : dr1}); - - await plotusToken.approve(tokenController.address, "20000000000000000000000",{from : dr2}); - await tokenController.lock("0x4452","20000000000000000000000",(86400*20),{from : dr2}); - - - await plotusToken.approve(tokenController.address, "20000000000000000000000",{from : dr3}); - await tokenController.lock("0x4452","20000000000000000000000",(86400*20),{from : dr3}); - - // console.log(await plotusNewInstance.getOpenMarkets()); - openMarkets = await plotusNewInstance.getOpenMarkets(); - - // console.log(`OpenMaket : ${openMarkets["_openMarkets"][0]}`); - - marketInstance = await Market.at(openMarkets["_openMarkets"][0]); - await increaseTime(10001); - assert.ok(marketInstance); - - // setting option price in eth - await marketConfig.setOptionPrice(1, 9); - await marketConfig.setOptionPrice(2, 18); - await marketConfig.setOptionPrice(3, 27); - - // set price - // user 1 - // set price lot - await MockUniswapRouterInstance.setPrice("1000000000000000"); - await marketConfig.setPrice("1000000000000000"); - await plotusToken.approve(tokenController.address, "100000000000000000000", { - from: user1, - }); - await marketInstance.placePrediction(plotusToken.address, "100000000000000000000", 2, 1, { from: user1 }); - - // user 2 - await MockUniswapRouterInstance.setPrice("2000000000000000"); - await marketConfig.setPrice("2000000000000000"); - await plotusToken.transfer(user2, "500000000000000000000"); - - await plotusToken.approve(tokenController.address, "400000000000000000000", { - from: user2, - }); - await marketInstance.placePrediction(plotusToken.address, "400000000000000000000", 2, 2, { from: user2 }); - // user 3 - await MockUniswapRouterInstance.setPrice("1000000000000000"); - await marketConfig.setPrice("1000000000000000"); - await plotusToken.transfer(user3, "500000000000000000000"); - await plotusToken.approve(tokenController.address, "210000000000000000000", { - from: user3, - }); - await marketInstance.placePrediction(plotusToken.address, "210000000000000000000", 2, 2, { from: user3 }); - await MockUniswapRouterInstance.setPrice("15000000000000000"); - await marketConfig.setPrice("15000000000000000"); - - await plotusToken.transfer(user4, "200000000000000000000"); - - await plotusToken.approve(tokenController.address, "123000000000000000000", { - from: user4, - }); - await marketInstance.placePrediction(plotusToken.address, "123000000000000000000", 3, 3, { from: user4 }); - - // user 5 - await MockUniswapRouterInstance.setPrice("12000000000000000"); - await marketConfig.setPrice("12000000000000000"); - await marketInstance.placePrediction("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", "1000000000000000000", 2, 4, { - value: "1000000000000000000", - from: user5, - }); - - // user 6 - await MockUniswapRouterInstance.setPrice("14000000000000000"); - await marketConfig.setPrice("14000000000000000"); - await marketInstance.placePrediction("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", "2000000000000000000", 3, 5, { - value: "2000000000000000000", - from: user6, - }); - // user 7 - await MockUniswapRouterInstance.setPrice("10000000000000000"); - await marketConfig.setPrice("10000000000000000"); - - await marketInstance.placePrediction("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", "1000000000000000000", 2, 2, { - value: "1000000000000000000", - from: user7, - }); - // user 8 - await MockUniswapRouterInstance.setPrice("45000000000000000"); - await marketConfig.setPrice("45000000000000000"); - await marketInstance.placePrediction("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", "3000000000000000000", 3, 3, { - value: "3000000000000000000", - from: user8, - }); - // user 9 - await MockUniswapRouterInstance.setPrice("51000000000000000"); - await marketConfig.setPrice("51000000000000000"); - await marketInstance.placePrediction("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", "1000000000000000000", 3, 1, { - value: "1000000000000000000", - from: user9, - }); - // user 10 - await MockUniswapRouterInstance.setPrice("12000000000000000"); - await marketConfig.setPrice("12000000000000000"); - await marketInstance.placePrediction("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", "2000000000000000000", 2, 4, { - value: "2000000000000000000", - from: user10, - }); - }); - - it("1.0 Prediction Points allocated properly in ether", async () => { - accounts = [user1, user2, user3, user4, user5, user6, user7, user8, user9, user10]; - options = [2, 2, 2, 3, 2, 3, 2, 3, 3, 2]; - getpredictionPoints = async (user, option, expected) => { - // return Prediction points of user - let predictionPoints = await marketInstance.getUserPredictionPoints(user, option); - predictionPoints = predictionPoints / 1; - return predictionPoints; - }; - predictionPointsExpected = [ - 1.755503471, - 83.41726908, - 11.21889102, - 306.0687072, - 255.1723181, - 627.5967878, - 116.4917104, - 634.1329064, - 36.98149537, - 721.7363059, - ]; - - for (let index = 0; index < 10; index++) { - let PredictionPoints = await getpredictionPoints(accounts[index], options[index]); - PredictionPoints = PredictionPoints / 1000; - PredictionPoints = PredictionPoints.toFixed(1); - await assert.equal(PredictionPoints, predictionPointsExpected[index].toFixed(1)); - } - await increaseTime(36001); - await marketInstance.calculatePredictionResult(1); - // plotus contract balance eth balance - - plotusBalanceBefore = web3.utils.fromWei(await web3.eth.getBalance(plotusNewAddress)); - lotBalanceBefore = await plotusToken.balanceOf(openMarkets["_openMarkets"][0]); - assert.equal(parseFloat(plotusBalanceBefore), (6.657336 + 0.145864).toFixed(5)); //stake-amount lost - assert.equal(parseFloat(web3.utils.fromWei(lotBalanceBefore)).toFixed(2), (494.95).toFixed(2)); - - await MockUniswapRouterInstance.setPrice("1000000000000000"); - await marketConfig.setPrice("1000000000000000"); - - plotusBalanceAfter = await web3.eth.getBalance(plotusNewAddress); - lotBalanceAfter = await plotusToken.balanceOf(openMarkets["_openMarkets"][0]); - assert.equal(parseFloat(plotusBalanceAfter), web3.utils.toWei("6.8032")); - assert.equal(parseFloat(web3.utils.fromWei(lotBalanceAfter)).toFixed(2), (494.9524).toFixed(2)); - assert.equal(parseFloat(web3.utils.fromWei(String(parseFloat(lotBalanceAfter) - parseFloat(lotBalanceBefore)))).toFixed(2), (0).toFixed(2)); - }); - - it("Raise dispute, accept, change the winninOption to 3", async() => { - await plotusToken.transfer(user11, "600000000000000000000"); - await plotusToken.approve(tokenController.address, "500000000000000000000", { - from: user11, - }); - let proposalId = await governance.getProposalLength(); - let marketETHBalanceBeforeDispute = await web3.eth.getBalance(marketInstance.address); - let registryBalanceBeforeDispute = await web3.eth.getBalance(plotusNewInstance.address); - assert.equal((await marketInstance.getMarketResults())[0]/1, 1); - await marketInstance.raiseDispute("500000000000000000000","","","", {from: user11}); - await governance.submitVote(proposalId, 1, {from:dr1}); - await governance.submitVote(proposalId, 1, {from:dr2}); - await governance.submitVote(proposalId, 1, {from:dr3}); - await increaseTime(604800); - await governance.closeProposal(proposalId); - await increaseTime(86401); - assert.equal((await marketInstance.getMarketResults())[0]/1, 3); - }); - - it("2.check total return for each user Prediction values in eth", async () => { - accounts = [user1, user2, user3, user4, user5, user6, user7, user8, user9, user10]; - options = [2, 2, 2, 3, 2, 3, 2, 3, 3, 2]; - getReturnsInEth = async (user) => { - // return userReturn in eth - const response = await marketInstance.getReturn(user); - let returnAmountInEth = web3.utils.fromWei(response[0][1]); - return returnAmountInEth; - }; - const returnInEthExpected = [0,0,0,0.5334908479,0.1998,3.091928045,0.5994,4.102320779,1.063460328,0.3996]; - - // calulate rewards for every user in eth - for (let index = 0; index < 10; index++) { - // check eth returns - let returns = await getReturnsInEth(accounts[index]); - assert.equal(parseFloat(returns).toFixed(2), returnInEthExpected[index].toFixed(2)); - } - }); - it("3.Check User Recived The appropriate amount as per new winning option", async () => { - accounts = [user1, user2, user3, user4, user5, user6, user7, user8, user9, user10]; - const totalReturnLotExpexted = [79.96, 239.88, 125.937, 173.2642411, 0, 103.1934096, 0, 104.2681193, 6.080729975, 0]; - const returnInEthExpected = [0,0,0,0.5334908479,0.1998,3.091928045,0.5994,4.102320779,1.063460328,0.3996]; - - for (let account of accounts) { - beforeClaim = await web3.eth.getBalance(account); - beforeClaimToken = await plotusToken.balanceOf(account); - await marketInstance.claimReturn(account); - afterClaim = await web3.eth.getBalance(account); - afterClaimToken = await plotusToken.balanceOf(account); - diff = afterClaim - beforeClaim; - diff = new BigNumber(diff); - conv = new BigNumber(1000000000000000000); - diff = diff / conv; - diff = diff.toFixed(2); - expectedInEth = returnInEthExpected[accounts.indexOf(account)].toFixed(2); - assert.equal(diff*1, expectedInEth*1); - - diffToken = afterClaimToken - beforeClaimToken; - diffToken = diffToken / conv; - diffToken = diffToken.toFixed(1); - expectedInLot = totalReturnLotExpexted[accounts.indexOf(account)].toFixed(1); - assert.equal(diffToken, expectedInLot); - } - // console.log((await web3.eth.getBalance(marketInstance.address)) / 1); - }); - // it("4. Market should have 0 balance after all claims", async () => { - // // console.log("Market Balance after claim" + (await web3.eth.getBalance(marketInstance.address)) / 1); - // assert.equal(parseFloat(await web3.eth.getBalance(marketInstance.address)), 0, "Market Balance must be 0 after all claims"); - // }); - it("5. Option price must be 0 after expire time", async () => { - await marketConfig.setMockPriceFlag(false); - let marketData = await marketInstance.getData(); - let optionPrice1 = parseFloat(marketData._optionPrice[0]); - let optionPrice2 = parseFloat(marketData._optionPrice[1]); - let optionPrice3 = parseFloat(marketData._optionPrice[2]); - assert.equal(optionPrice1, 0); - assert.equal(optionPrice2, 0); - assert.equal(optionPrice3, 0); - }); -}); diff --git a/test/11_plotus2MetaTx.js b/test/11_plotus2MetaTx.js new file mode 100644 index 000000000..32c2147e0 --- /dev/null +++ b/test/11_plotus2MetaTx.js @@ -0,0 +1,311 @@ +const { assert } = require("chai"); + +const OwnedUpgradeabilityProxy = artifacts.require("OwnedUpgradeabilityProxy"); +const Master = artifacts.require("Master"); +const MarketConfig = artifacts.require("MockConfig"); +const PlotusToken = artifacts.require("MockPLOT"); +const Governance = artifacts.require("Governance"); +const ProposalCategory = artifacts.require("ProposalCategory"); +const TokenController = artifacts.require("TokenController"); +const BLOT = artifacts.require("BLOT"); +const AllMarkets = artifacts.require("MockAllMarkets"); +const MarketUtility = artifacts.require("MockConfig"); //mock +const MemberRoles = artifacts.require("MemberRoles"); +const MarketCreationRewards = artifacts.require('MarketCreationRewards'); +const BigNumber = require("bignumber.js"); +const { increaseTimeTo } = require("./utils/increaseTime.js"); +const encode1 = require('./utils/encoder.js').encode1; +const encode3 = require("./utils/encoder.js").encode3; +const signAndExecuteMetaTx = require("./utils/signAndExecuteMetaTx.js").signAndExecuteMetaTx; +const BN = require('bn.js'); + +const assertRevert = require("./utils/assertRevert.js").assertRevert; +const increaseTime = require("./utils/increaseTime.js").increaseTime; +const latestTime = require("./utils/latestTime.js").latestTime; +const encode = require("./utils/encoder.js").encode; +const gvProposal = require("./utils/gvProposal.js").gvProposalWithIncentiveViaTokenHolder; +const { toHex, toWei, toChecksumAddress } = require("./utils/ethTools"); +// get etherum accounts +// swap ether with LOT +let timeNow, + marketData, + expireTme, + priceOption1, + priceOption2, + priceOption3, + option1RangeMIN, + option1RangeMAX, + option2RangeMIN, + option2RangeMAX, + option3RangeMIX, + marketStatus, + option3RangeMAX, governance, + marketETHBalanceBeforeDispute, + marketIncentives; + +let privateKeyList = ["fb437e3e01939d9d4fef43138249f23dc1d0852e69b0b5d1647c087f869fabbd","7c85a1f1da3120c941b83d71a154199ee763307683f206b98ad92c3b4e0af13e","ecc9b35bf13bd5459350da564646d05c5664a7476fe5acdf1305440f88ed784c","f4470c3fca4dbef1b2488d016fae25978effc586a1f83cb29ac8cb6ab5bc2d50","141319b1a84827e1046e93741bf8a9a15a916d49684ab04925ac4ce4573eea23","d54b606094287758dcf19064a8d91c727346aadaa9388732e73c4315b7c606f9","49030e42ce4152e715a7ddaa10e592f8e61d00f70ef11f48546711f159d985df","b96761b1e7ebd1e8464a78a98fe52f53ce6035c32b4b2b12307a629a551ff7cf","d4786e2581571c863c7d12231c3afb6d4cef390c0ac9a24b243293721d28ea95","ed28e3d3530544f1cf2b43d1956b7bd13b63c612d963a8fb37387aa1a5e11460","05b127365cf115d4978a7997ee98f9b48f0ddc552b981c18aa2ee1b3e6df42c6","9d11dd6843f298b01b34bd7f7e4b1037489871531d14b58199b7cba1ac0841e6","f79e90fa4091de4fc2ec70f5bf67b24393285c112658e0d810e6bd711387fbb9","99f1fc0f09230ce745b6a256ba7082e6e51a2907abda3d9e735a5c8188bb4ba1","477f86cce983b9c91a36fdcd4a7ce21144a08dee9b1aafb91b9c70e57f717ce6","b03d2e6bb4a7d71c66a66ff9e9c93549cae4b593f634a4ea2a1f79f94200f5b4","9ddc0f53a81e631dcf39d5155f41ec12ed551b731efc3224f410667ba07b37dc","cf087ff9ae7c9954ad8612d071e5cdf34a6024ee1ae477217639e63a802a53dd","b64f62b94babb82cc78d3d1308631ae221552bb595202fc1d267e1c29ce7ba60","a91e24875f8a534497459e5ccb872c4438be3130d8d74b7e1104c5f94cdcf8c2","4f49f3d029eeeb3fed14d59625acd088b6b34f3b41c527afa09d29e4a7725c32","179795fd7ac7e7efcba3c36d539a1e8659fb40d77d0a3fab2c25562d99793086","4ba37d0b40b879eceaaca2802a1635f2e6d86d5c31e3ff2d2fd13e68dd2a6d3d","6b7f5dfba9cd3108f1410b56f6a84188eee23ab48a3621b209a67eea64293394","870c540da9fafde331a3316cee50c17ad76ddb9160b78b317bef2e6f6fc4bac0","470b4cccaea895d8a5820aed088357e380d66b8e7510f0a1ea9b575850160241","8a55f8942af0aec1e0df3ab328b974a7888ffd60ded48cc6862013da0f41afbc","2e51e8409f28baf93e665df2a9d646a1bf9ac8703cbf9a6766cfdefa249d5780","99ef1a23e95910287d39493d8d9d7d1f0b498286f2b1fdbc0b01495f10cf0958","6652200c53a4551efe2a7541072d817562812003f9d9ef0ec17995aa232378f8","39c6c01194df72dda97da2072335c38231ced9b39afa280452afcca901e73643","12097e411d948f77b7b6fa4656c6573481c1b4e2864c1fca9d5b296096707c45","cbe53bf1976aee6cec830a848c6ac132def1503cffde82ccfe5bd15e75cbaa72","eeab5dcfff92dbabb7e285445aba47bd5135a4a3502df59ac546847aeb5a964f","5ea8279a578027abefab9c17cef186cccf000306685e5f2ee78bdf62cae568dd","0607767d89ad9c7686dbb01b37248290b2fa7364b2bf37d86afd51b88756fe66","e4fd5f45c08b52dae40f4cdff45e8681e76b5af5761356c4caed4ca750dc65cd","145b1c82caa2a6d703108444a5cf03e9cb8c3cd3f19299582a564276dbbba734","736b22ec91ae9b4b2b15e8d8c220f6c152d4f2228f6d46c16e6a9b98b4733120","ac776cb8b40f92cdd307b16b83e18eeb1fbaa5b5d6bd992b3fda0b4d6de8524c","65ba30e2202fdf6f37da0f7cfe31dfb5308c9209885aaf4cef4d572fd14e2903","54e8389455ec2252de063e83d3ce72529d674e6d2dc2070661f01d4f76b63475","fbbbfb525dd0255ee332d51f59648265aaa20c2e9eff007765cf4d4a6940a849","8de5e418f34d04f6ea947ce31852092a24a705862e6b810ca9f83c2d5f9cda4d","ea6040989964f012fd3a92a3170891f5f155430b8bbfa4976cde8d11513b62d9","14d94547b5deca767137fbd14dae73e888f3516c742fad18b83be333b38f0b88","47f05203f6368d56158cda2e79167777fc9dcb0c671ef3aabc205a1636c26a29"]; + +contract("Rewards-Market", async function(users) { + describe("Scenario2", async () => { + it("0.0", async () => { + masterInstance = await OwnedUpgradeabilityProxy.deployed(); + masterInstance = await Master.at(masterInstance.address); + plotusToken = await PlotusToken.deployed(); + BLOTInstance = await BLOT.deployed(); + tokenController =await TokenController.at(await masterInstance.getLatestAddress(web3.utils.toHex("TC"))); + governance = await masterInstance.getLatestAddress(web3.utils.toHex("GV")); + governance = await Governance.at(governance); + marketConfig = await masterInstance.getLatestAddress(web3.utils.toHex("MU")); + marketConfig = await MarketConfig.at(marketConfig); + timeNow = await latestTime(); + + allMarkets = await AllMarkets.at(await masterInstance.getLatestAddress(web3.utils.toHex("AM"))); + marketIncentives = await MarketCreationRewards.at(await masterInstance.getLatestAddress(web3.utils.toHex("MC"))); + await increaseTime(5 * 3600); + await plotusToken.transfer(marketIncentives.address,toWei(100000)); + await plotusToken.transfer(users[11],toWei(100000)); + await plotusToken.transfer(users[12],toWei(100000)); + + let nullAddress = "0x0000000000000000000000000000"; + + await allMarkets.createMarket(0, 0,{from:users[11],gasPrice:500000}); + // await marketIncentives.claimCreationReward(100,{from:users[11]}); + }); + + + it("Scenario 2:All losers, no winners", async () => { + let i; + let totalDepositedPlot = toWei(1000); + let predictionVal = [0,100, 400, 210, 123, 500, 700, 200, 50, 300, 150]; + let options=[0,2,2,2,3,2,3,2,3,3,2]; + for(i=1; i<11;i++){ + await plotusToken.transfer(users[i], toWei(2000)); + await plotusToken.approve(allMarkets.address, toWei(100000), { from: users[i] }); + let functionSignature = encode3("depositAndPlacePrediction(uint,uint,address,uint64,uint256)", totalDepositedPlot, 7, plotusToken.address, predictionVal[i]*1e8, options[i]); + await marketConfig.setNextOptionPrice(options[i]*9); + await signAndExecuteMetaTx( + privateKeyList[i], + users[i], + functionSignature, + allMarkets, + "AM" + ); + } + + let relayerBalBefore = await plotusToken.balanceOf(users[0]); + await allMarkets.claimRelayerRewards(); + let relayerBalAfter = await plotusToken.balanceOf(users[0]); + + assert.equal(Math.round((relayerBalAfter-relayerBalBefore)/1e15),49.194*1e3); + + + let betpoints = [0,5444.44444, 21777.77777, 11433.33333, 4464.44444, 27222.22222, 25407.40740, 10888.88888, 1814.81481, 10888.88888, 8166.66666]; + + + for(i=1;i<11;i++) + { + let betPointUser = (await allMarkets.getUserPredictionPoints(users[i],7,options[i]))/1e5; + assert.equal(betPointUser,betpoints[i]); + let unusedBal = await allMarkets.getUserUnusedBalance(users[i]); + assert.equal(totalDepositedPlot/1e18-unusedBal[0]/1e18,predictionVal[i]); + } + + await increaseTime(8*60*60); + + await allMarkets.postResultMock(1,7); + await plotusToken.transfer(users[12], "700000000000000000000"); + await plotusToken.approve(allMarkets.address, "500000000000000000000", { + from: users[12], + }); + let proposalId = await governance.getProposalLength(); + await allMarkets.raiseDispute(7, "500000000000000000000","","","", {from: users[12]}); + await increaseTime(604810); + await governance.closeProposal(proposalId/1); + + await increaseTime(60*61); + + for(i=1;i<11;i++) + { + let reward = await allMarkets.getReturn(users[i],7); + assert.equal(Math.round(reward/1e2),0); + let plotBalBefore = await plotusToken.balanceOf(users[i]); + let plotEthUnused = await allMarkets.getUserUnusedBalance(users[i]); + functionSignature = encode3("withdraw(uint,uint)", plotEthUnused[0].iadd(plotEthUnused[1]), 100); + await signAndExecuteMetaTx( + privateKeyList[i], + users[i], + functionSignature, + allMarkets, + "AM" + ); + let plotBalAfter = await plotusToken.balanceOf(users[i]); + assert.equal(Math.round((plotBalAfter-plotBalBefore)/1e18),Math.round((totalDepositedPlot/1e18-predictionVal[i])/1+reward/1e8)); + } + + let marketCreatorReward = await marketIncentives.getPendingMarketCreationRewards(users[11]); + assert.equal(133917000,Math.round(marketCreatorReward[1]/1e11)); + + let plotBalBeforeCreator = await plotusToken.balanceOf(users[11]); + + functionSignature = encode3("claimCreationReward(uint256)", 100); + await signAndExecuteMetaTx( + privateKeyList[11], + users[11], + functionSignature, + marketIncentives, + "MC" + ); + + let plotBalAfterCreator = await plotusToken.balanceOf(users[11]); + + assert.equal(Math.round((plotBalAfterCreator-plotBalBeforeCreator)/1e11),133917000); + + + }); + }); +}); + + +contract("Rewards-Market", async function(users) { + describe("Scenario2", async () => { + it("0.0", async () => { + masterInstance = await OwnedUpgradeabilityProxy.deployed(); + masterInstance = await Master.at(masterInstance.address); + plotusToken = await PlotusToken.deployed(); + BLOTInstance = await BLOT.deployed(); + tokenController =await TokenController.at(await masterInstance.getLatestAddress(web3.utils.toHex("TC"))); + governance = await masterInstance.getLatestAddress(web3.utils.toHex("GV")); + governance = await Governance.at(governance); + marketConfig = await masterInstance.getLatestAddress(web3.utils.toHex("MU")); + marketConfig = await MarketConfig.at(marketConfig); + timeNow = await latestTime(); + + allMarkets = await AllMarkets.at(await masterInstance.getLatestAddress(web3.utils.toHex("AM"))); + marketIncentives = await MarketCreationRewards.at(await masterInstance.getLatestAddress(web3.utils.toHex("MC"))); + await increaseTime(5 * 3600); + await plotusToken.transfer(marketIncentives.address,toWei(100000)); + await plotusToken.transfer(users[11],toWei(400000)); + await plotusToken.transfer(users[12],toWei(100000)); + await plotusToken.approve(tokenController.address,toWei(400000),{from:users[11]}); + await tokenController.lock(toHex("SM"),toWei(300000),30*3600*24,{from:users[11]}); + + let nullAddress = "0x0000000000000000000000000000"; + + await allMarkets.createMarket(0, 0,{from:users[11],gasPrice:500000}); + // await marketIncentives.claimCreationReward(100,{from:users[11]}); + }); + + it("Scenario 2:All losers, no winners", async () => { + let i; + let totalDepositedPlot = toWei(1000); + let predictionVal = [0,100, 400, 210, 123, 500, 700, 200, 50, 300, 150]; + let options=[0,2,2,2,3,2,3,2,3,3,2]; + for(i=1; i<11;i++){ + await plotusToken.transfer(users[i], toWei(2000)); + await plotusToken.approve(allMarkets.address, toWei(100000), { from: users[i] }); + let functionSignature = encode3("depositAndPlacePrediction(uint,uint,address,uint64,uint256)", totalDepositedPlot, 7, plotusToken.address, predictionVal[i]*1e8, options[i]); + await marketConfig.setNextOptionPrice(options[i]*9); + await signAndExecuteMetaTx( + privateKeyList[i], + users[i], + functionSignature, + allMarkets, + "AM" + ); + } + + let relayerBalBefore = await plotusToken.balanceOf(users[0]); + await allMarkets.claimRelayerRewards(); + let relayerBalAfter = await plotusToken.balanceOf(users[0]); + + assert.equal(Math.round((relayerBalAfter-relayerBalBefore)/1e15),49.194*1e3); + + + let betpoints = [0,5444.44444, 21777.77777, 11433.33333, 4464.44444, 27222.22222, 25407.40740, 10888.88888, 1814.81481, 10888.88888, 8166.66666]; + + for(i=1;i<11;i++) + { + let betPointUser = (await allMarkets.getUserPredictionPoints(users[i],7,options[i]))/1e5; + assert.equal(betPointUser,betpoints[i]); + let unusedBal = await allMarkets.getUserUnusedBalance(users[i]); + assert.equal(totalDepositedPlot/1e18-unusedBal[0]/1e18,predictionVal[i]); + } + + await increaseTime(8*60*60); + + await allMarkets.postResultMock(1,7); + + await plotusToken.transfer(users[12], "700000000000000000000"); + await plotusToken.approve(allMarkets.address, "500000000000000000000", { + from: users[12], + }); + let proposalId = await governance.getProposalLength(); + await allMarkets.raiseDispute(7, "500000000000000000000","","","", {from: users[12]}); + + await plotusToken.transfer(users[13], "20000000000000000000000"); + await plotusToken.transfer(users[14], "20000000000000000000000"); + await plotusToken.transfer(users[15], "20000000000000000000000"); + await plotusToken.approve(tokenController.address, "20000000000000000000000",{from : users[13]}); + await tokenController.lock("0x4452","20000000000000000000000",(86400*20),{from : users[13]}); + + await plotusToken.approve(tokenController.address, "20000000000000000000000",{from : users[14]}); + await tokenController.lock("0x4452","20000000000000000000000",(86400*20),{from : users[14]}); + + + await plotusToken.approve(tokenController.address, "20000000000000000000000",{from : users[15]}); + await tokenController.lock("0x4452","20000000000000000000000",(86400*20),{from : users[15]}); + + await governance.submitVote(proposalId, 1, {from:users[13]}); + await governance.submitVote(proposalId, 1, {from:users[14]}); + await governance.submitVote(proposalId, 1, {from:users[15]}); + await increaseTime(604800); + await governance.closeProposal(proposalId); + await increaseTime(86401); + assert.equal((await allMarkets.getMarketResults(7))[0]/1, 3); + + await increaseTime(60*61); + + let userRewardPlot = [0, 0, 0, 0, 272.833504, 0, 1552.710998, 0, 110.907928, 665.447570, 0]; + + for(i=1;i<11;i++) + { + let reward = await allMarkets.getReturn(users[i],7); + assert.equal(Math.round(reward/1e2),userRewardPlot[i]*1e6); + if(reward > 0) { + let plotBalBefore = await plotusToken.balanceOf(users[i]); + let plotEthUnused = await allMarkets.getUserUnusedBalance(users[i]); + functionSignature = encode3("withdraw(uint,uint)", plotEthUnused[0].iadd(plotEthUnused[1]), 100); + + await signAndExecuteMetaTx( + privateKeyList[i], + users[i], + functionSignature, + allMarkets, + "AM" + ); + let plotBalAfter = await plotusToken.balanceOf(users[i]); + assert.equal(Math.round((plotBalAfter-plotBalBefore)/1e18),Math.round((totalDepositedPlot/1e18-predictionVal[i])/1+reward/1e8)); + } + } + + let marketCreatorReward = await marketIncentives.getPendingMarketCreationRewards(users[11]); + assert.equal(764400000,Math.round(marketCreatorReward[1]/1e11)); + + let plotBalBeforeCreator = await plotusToken.balanceOf(users[11]); + + functionSignature = encode3("claimCreationReward(uint256)", 100); + await signAndExecuteMetaTx( + privateKeyList[11], + users[11], + functionSignature, + marketIncentives, + "MC" + ); + + let plotBalAfterCreator = await plotusToken.balanceOf(users[11]); + + assert.equal(((plotBalAfterCreator-plotBalBeforeCreator)/1e11).toFixed(1),764400000); + + }); + }); +}); \ No newline at end of file diff --git a/test/12_plotus3.js b/test/12_plotus3.js deleted file mode 100644 index 4872ccc33..000000000 --- a/test/12_plotus3.js +++ /dev/null @@ -1,239 +0,0 @@ -const { assert } = require("chai"); -const OwnedUpgradeabilityProxy = artifacts.require("OwnedUpgradeabilityProxy"); -const Market = artifacts.require("MockMarket"); -const Plotus = artifacts.require("MarketRegistry"); -const Master = artifacts.require("Master"); -const MarketConfig = artifacts.require("MockConfig"); -const PlotusToken = artifacts.require("MockPLOT"); -const BLOT = artifacts.require("BLOT"); -const TokenController = artifacts.require("TokenController"); -const MockUniswapRouter = artifacts.require("MockUniswapRouter"); -const BigNumber = require("bignumber.js"); - -const web3 = Market.web3; -const increaseTime = require("./utils/increaseTime.js").increaseTime; -// get etherum accounts -// swap ether with LOT - -contract("Market", async function([user1, user2, user3, user4, user5, user6, user7, user8, user9, user10]) { - it("Place the prediction with ether", async () => { - masterInstance = await OwnedUpgradeabilityProxy.deployed(); - masterInstance = await Master.at(masterInstance.address); - plotusToken = await PlotusToken.deployed(); - BLOTInstance = await BLOT.deployed(); - MockUniswapRouterInstance = await MockUniswapRouter.deployed(); - plotusNewAddress = await masterInstance.getLatestAddress(web3.utils.toHex("PL")); - tokenController =await TokenController.at(await masterInstance.getLatestAddress(web3.utils.toHex("TC"))); - plotusNewInstance = await Plotus.at(plotusNewAddress); - marketConfig = await plotusNewInstance.marketUtility(); - marketConfig = await MarketConfig.at(marketConfig); - // console.log(await plotusNewInstance.getOpenMarkets()); - openMarkets = await plotusNewInstance.getOpenMarkets(); - - // console.log(`OpenMaket : ${openMarkets["_openMarkets"][0]}`); - - marketInstance = await Market.at(openMarkets["_openMarkets"][0]); - await increaseTime(10001); - assert.ok(marketInstance); - - // setting option price in eth - await marketConfig.setOptionPrice(1, 9); - await marketConfig.setOptionPrice(2, 18); - await marketConfig.setOptionPrice(3, 27); - - // set price - // user 1 - // set price lot - await MockUniswapRouterInstance.setPrice("1000000000000000"); - await marketConfig.setPrice("1000000000000000"); - await plotusToken.approve(tokenController.address, "100000000000000000000", { - from: user1, - }); - await marketInstance.placePrediction(plotusToken.address, "100000000000000000000", 1, 1, { from: user1 }); - - // user 2 - await MockUniswapRouterInstance.setPrice("2000000000000000"); - await marketConfig.setPrice("2000000000000000"); - await plotusToken.transfer(user2, "500000000000000000000"); - - await plotusToken.approve(tokenController.address, "400000000000000000000", { - from: user2, - }); - await marketInstance.placePrediction(plotusToken.address, "400000000000000000000", 1, 2, { from: user2 }); - // user 3 - await MockUniswapRouterInstance.setPrice("1000000000000000"); - await marketConfig.setPrice("1000000000000000"); - await plotusToken.transfer(user3, "500000000000000000000"); - await plotusToken.approve(tokenController.address, "210000000000000000000", { - from: user3, - }); - await marketInstance.placePrediction(plotusToken.address, "210000000000000000000", 1, 2, { from: user3 }); - await MockUniswapRouterInstance.setPrice("15000000000000000"); - await marketConfig.setPrice("15000000000000000"); - - await plotusToken.transfer(user4, "200000000000000000000"); - - await plotusToken.approve(tokenController.address, "123000000000000000000", { - from: user4, - }); - await marketInstance.placePrediction(plotusToken.address, "123000000000000000000", 1, 3, { from: user4 }); - - // user 5 - await MockUniswapRouterInstance.setPrice("12000000000000000"); - await marketConfig.setPrice("12000000000000000"); - await marketInstance.placePrediction("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", "1000000000000000000", 1, 4, { - value: "1000000000000000000", - from: user5, - }); - - // user 6 - await MockUniswapRouterInstance.setPrice("14000000000000000"); - await marketConfig.setPrice("14000000000000000"); - await marketInstance.placePrediction("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", "2000000000000000000", 1, 5, { - value: "2000000000000000000", - from: user6, - }); - // user 7 - await MockUniswapRouterInstance.setPrice("10000000000000000"); - await marketConfig.setPrice("10000000000000000"); - - await marketInstance.placePrediction("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", "1000000000000000000", 1, 2, { - value: "1000000000000000000", - from: user7, - }); - // user 8 - await MockUniswapRouterInstance.setPrice("45000000000000000"); - await marketConfig.setPrice("45000000000000000"); - await marketInstance.placePrediction("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", "3000000000000000000", 1, 3, { - value: "3000000000000000000", - from: user8, - }); - // user 9 - await MockUniswapRouterInstance.setPrice("51000000000000000"); - await marketConfig.setPrice("51000000000000000"); - await marketInstance.placePrediction("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", "1000000000000000000", 1, 1, { - value: "1000000000000000000", - from: user9, - }); - // user 10 - await MockUniswapRouterInstance.setPrice("12000000000000000"); - await marketConfig.setPrice("12000000000000000"); - await marketInstance.placePrediction("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", "2000000000000000000", 1, 4, { - value: "2000000000000000000", - from: user10, - }); - }); - - it("1.Prediction Points allocated properly in ether", async () => { - accounts = [user1, user2, user3, user4, user5, user6, user7, user8, user9, user10]; - options = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1]; - getPredictionPoints = async (user, option, expected) => { - // return Prediction points of user - let PredictionPoins = await marketInstance.getUserPredictionPoints(user, option); - PredictionPoins = PredictionPoins / 1; - return PredictionPoins; - }; - PredictionPointsExpected = [ - 3.511006943, - 166.8345382, - 22.43778204, - 918.2061216, - 510.3446361, - 1882.790363, - 232.9834208, - 1902.398719, - 110.9444861, - 1443.472612, - ]; - - for (let index = 0; index < 10; index++) { - let PredictionPoints = await getPredictionPoints(accounts[index], options[index]); - PredictionPoints = PredictionPoints / 1000; - PredictionPoints = PredictionPoints.toFixed(1); - await assert.equal(PredictionPoints, PredictionPointsExpected[index].toFixed(1)); - - } - - // close market - await increaseTime(36001); - await marketInstance.calculatePredictionResult(1); - await increaseTime(36001); - // plotus contract balance eth balance - - plotusBalanceBefore = web3.utils.fromWei(await web3.eth.getBalance(plotusNewAddress)); - lotBalanceBefore = await plotusToken.balanceOf(openMarkets["_openMarkets"][0]); - assert.equal(parseFloat(plotusBalanceBefore), 0.01); - assert.equal(parseFloat(web3.utils.fromWei(lotBalanceBefore)).toFixed(2), (832.5835).toFixed(2)); - - await MockUniswapRouterInstance.setPrice("1000000000000000"); - await marketConfig.setPrice("1000000000000000"); - await increaseTime(360001); - - plotusBalanceAfter = web3.utils.fromWei(await web3.eth.getBalance(plotusNewAddress)); - lotBalanceAfter = await plotusToken.balanceOf(openMarkets["_openMarkets"][0]); - assert.equal(parseFloat(plotusBalanceBefore), 0.01); - assert.equal(parseFloat(web3.utils.fromWei(lotBalanceAfter)).toFixed(2), (832.5835).toFixed(2)); - assert.equal(parseFloat(web3.utils.fromWei(String(parseFloat(lotBalanceAfter) - parseFloat(lotBalanceBefore)))).toFixed(2), (0).toFixed(2)); - }); - - it("2.check total return for each user Prediction values in eth", async () => { - accounts = [user1, user2, user3, user4, user5, user6, user7, user8, user9, user10]; - options = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1]; - getReturnsInEth = async (user) => { - // return userReturn in eth - const response = await marketInstance.getReturn(user); - let returnAmountInEth = web3.utils.fromWei(response[0][1]); - return returnAmountInEth; - }; - - const returnInEthExpected = [0, 0, 0, 0, 0.999, 1.998, 0.999, 2.997, 0.999, 1.998]; - // calulate rewards for every user in eth - - for (let index = 0; index < 10; index++) { - // check eth returns - let returns = await getReturnsInEth(accounts[index]); - assert.equal(parseFloat(returns).toFixed(2), returnInEthExpected[index].toFixed(2)); - } - }); - it("3.Check User Recived The appropriate amount", async () => { - accounts = [user1, user2, user3, user4, user5, user6, user7, user8, user9, user10]; - const totalReturnLotExpexted = [99.9, 399.8, 209.895, 122.9385, 0, 0, 0, 0, 0, 0]; - const returnInEthExpected = [0, 0, 0, 0, 0.999, 1.998, 0.999, 2.997, 0.999, 1.998]; - - - for (let account of accounts) { - beforeClaim = await web3.eth.getBalance(account); - beforeClaimToken = await plotusToken.balanceOf(account); - await marketInstance.claimReturn(account); - afterClaim = await web3.eth.getBalance(account); - afterClaimToken = await plotusToken.balanceOf(account); - diff = afterClaim - beforeClaim; - diff = new BigNumber(diff); - conv = new BigNumber(1000000000000000000); - diff = diff / conv; - diff = diff.toFixed(2); - expectedInEth = returnInEthExpected[accounts.indexOf(account)].toFixed(2); - assert.equal(diff*1, expectedInEth*1); - - diffToken = afterClaimToken - beforeClaimToken; - diffToken = diffToken / conv; - diffToken = diffToken.toFixed(1); - expectedInLot = totalReturnLotExpexted[accounts.indexOf(account)].toFixed(1); - assert.equal(diffToken, expectedInLot); - } - }); - // it("4. Market should have 0 balance after all claims", async () => { - // // console.log("Market Balance after claim" + (await web3.eth.getBalance(marketInstance.address)) / 1); - // assert.equal(parseFloat(await web3.eth.getBalance(marketInstance.address)), 0, "Market Balance must be 0 after all claims"); - // }); - it("5. Option price must be 0 after expire time", async () => { - await marketConfig.setMockPriceFlag(false); - let marketData = await marketInstance.getData(); - let optionPrice1 = parseFloat(marketData._optionPrice[0]); - let optionPrice2 = parseFloat(marketData._optionPrice[1]); - let optionPrice3 = parseFloat(marketData._optionPrice[2]); - assert.equal(optionPrice1, 0); - assert.equal(optionPrice2, 0); - assert.equal(optionPrice3, 0); - }); -}); diff --git a/test/12_plotus3MetaTx.js b/test/12_plotus3MetaTx.js new file mode 100644 index 000000000..afdaf0c00 --- /dev/null +++ b/test/12_plotus3MetaTx.js @@ -0,0 +1,247 @@ +const { assert } = require("chai"); + +const OwnedUpgradeabilityProxy = artifacts.require("OwnedUpgradeabilityProxy"); +const Master = artifacts.require("Master"); +const MarketConfig = artifacts.require("MockConfig"); +const PlotusToken = artifacts.require("MockPLOT"); +const Governance = artifacts.require("Governance"); +const ProposalCategory = artifacts.require("ProposalCategory"); +const TokenController = artifacts.require("TokenController"); +const BLOT = artifacts.require("BLOT"); +const AllMarkets = artifacts.require("MockAllMarkets"); +const MarketUtility = artifacts.require("MockConfig"); //mock +const MemberRoles = artifacts.require("MemberRoles"); +const MarketCreationRewards = artifacts.require('MarketCreationRewards'); +const BigNumber = require("bignumber.js"); +const { increaseTimeTo } = require("./utils/increaseTime.js"); +const encode1 = require('./utils/encoder.js').encode1; +const encode3 = require("./utils/encoder.js").encode3; +const signAndExecuteMetaTx = require("./utils/signAndExecuteMetaTx.js").signAndExecuteMetaTx; +const BN = require('bn.js'); + +const assertRevert = require("./utils/assertRevert.js").assertRevert; +const increaseTime = require("./utils/increaseTime.js").increaseTime; +const latestTime = require("./utils/latestTime.js").latestTime; +const encode = require("./utils/encoder.js").encode; +const gvProposal = require("./utils/gvProposal.js").gvProposalWithIncentiveViaTokenHolder; +const { toHex, toWei, toChecksumAddress } = require("./utils/ethTools"); +// get etherum accounts +// swap ether with LOT +let timeNow, + marketData, + expireTme, + priceOption1, + priceOption2, + priceOption3, + option1RangeMIN, + option1RangeMAX, + option2RangeMIN, + option2RangeMAX, + option3RangeMIX, + marketStatus, + option3RangeMAX, governance, + marketETHBalanceBeforeDispute, + marketIncentives; + +let privateKeyList = ["fb437e3e01939d9d4fef43138249f23dc1d0852e69b0b5d1647c087f869fabbd","7c85a1f1da3120c941b83d71a154199ee763307683f206b98ad92c3b4e0af13e","ecc9b35bf13bd5459350da564646d05c5664a7476fe5acdf1305440f88ed784c","f4470c3fca4dbef1b2488d016fae25978effc586a1f83cb29ac8cb6ab5bc2d50","141319b1a84827e1046e93741bf8a9a15a916d49684ab04925ac4ce4573eea23","d54b606094287758dcf19064a8d91c727346aadaa9388732e73c4315b7c606f9","49030e42ce4152e715a7ddaa10e592f8e61d00f70ef11f48546711f159d985df","b96761b1e7ebd1e8464a78a98fe52f53ce6035c32b4b2b12307a629a551ff7cf","d4786e2581571c863c7d12231c3afb6d4cef390c0ac9a24b243293721d28ea95","ed28e3d3530544f1cf2b43d1956b7bd13b63c612d963a8fb37387aa1a5e11460","05b127365cf115d4978a7997ee98f9b48f0ddc552b981c18aa2ee1b3e6df42c6","9d11dd6843f298b01b34bd7f7e4b1037489871531d14b58199b7cba1ac0841e6","f79e90fa4091de4fc2ec70f5bf67b24393285c112658e0d810e6bd711387fbb9","99f1fc0f09230ce745b6a256ba7082e6e51a2907abda3d9e735a5c8188bb4ba1","477f86cce983b9c91a36fdcd4a7ce21144a08dee9b1aafb91b9c70e57f717ce6","b03d2e6bb4a7d71c66a66ff9e9c93549cae4b593f634a4ea2a1f79f94200f5b4","9ddc0f53a81e631dcf39d5155f41ec12ed551b731efc3224f410667ba07b37dc","cf087ff9ae7c9954ad8612d071e5cdf34a6024ee1ae477217639e63a802a53dd","b64f62b94babb82cc78d3d1308631ae221552bb595202fc1d267e1c29ce7ba60","a91e24875f8a534497459e5ccb872c4438be3130d8d74b7e1104c5f94cdcf8c2","4f49f3d029eeeb3fed14d59625acd088b6b34f3b41c527afa09d29e4a7725c32","179795fd7ac7e7efcba3c36d539a1e8659fb40d77d0a3fab2c25562d99793086","4ba37d0b40b879eceaaca2802a1635f2e6d86d5c31e3ff2d2fd13e68dd2a6d3d","6b7f5dfba9cd3108f1410b56f6a84188eee23ab48a3621b209a67eea64293394","870c540da9fafde331a3316cee50c17ad76ddb9160b78b317bef2e6f6fc4bac0","470b4cccaea895d8a5820aed088357e380d66b8e7510f0a1ea9b575850160241","8a55f8942af0aec1e0df3ab328b974a7888ffd60ded48cc6862013da0f41afbc","2e51e8409f28baf93e665df2a9d646a1bf9ac8703cbf9a6766cfdefa249d5780","99ef1a23e95910287d39493d8d9d7d1f0b498286f2b1fdbc0b01495f10cf0958","6652200c53a4551efe2a7541072d817562812003f9d9ef0ec17995aa232378f8","39c6c01194df72dda97da2072335c38231ced9b39afa280452afcca901e73643","12097e411d948f77b7b6fa4656c6573481c1b4e2864c1fca9d5b296096707c45","cbe53bf1976aee6cec830a848c6ac132def1503cffde82ccfe5bd15e75cbaa72","eeab5dcfff92dbabb7e285445aba47bd5135a4a3502df59ac546847aeb5a964f","5ea8279a578027abefab9c17cef186cccf000306685e5f2ee78bdf62cae568dd","0607767d89ad9c7686dbb01b37248290b2fa7364b2bf37d86afd51b88756fe66","e4fd5f45c08b52dae40f4cdff45e8681e76b5af5761356c4caed4ca750dc65cd","145b1c82caa2a6d703108444a5cf03e9cb8c3cd3f19299582a564276dbbba734","736b22ec91ae9b4b2b15e8d8c220f6c152d4f2228f6d46c16e6a9b98b4733120","ac776cb8b40f92cdd307b16b83e18eeb1fbaa5b5d6bd992b3fda0b4d6de8524c","65ba30e2202fdf6f37da0f7cfe31dfb5308c9209885aaf4cef4d572fd14e2903","54e8389455ec2252de063e83d3ce72529d674e6d2dc2070661f01d4f76b63475","fbbbfb525dd0255ee332d51f59648265aaa20c2e9eff007765cf4d4a6940a849","8de5e418f34d04f6ea947ce31852092a24a705862e6b810ca9f83c2d5f9cda4d","ea6040989964f012fd3a92a3170891f5f155430b8bbfa4976cde8d11513b62d9","14d94547b5deca767137fbd14dae73e888f3516c742fad18b83be333b38f0b88","47f05203f6368d56158cda2e79167777fc9dcb0c671ef3aabc205a1636c26a29"]; + +contract("Rewards-Market", async function(users) { + describe("Scenario3", async () => { + it("0.0", async () => { + masterInstance = await OwnedUpgradeabilityProxy.deployed(); + masterInstance = await Master.at(masterInstance.address); + plotusToken = await PlotusToken.deployed(); + BLOTInstance = await BLOT.deployed(); + tokenController =await TokenController.at(await masterInstance.getLatestAddress(web3.utils.toHex("TC"))); + governance = await masterInstance.getLatestAddress(web3.utils.toHex("GV")); + governance = await Governance.at(governance); + marketConfig = await masterInstance.getLatestAddress(web3.utils.toHex("MU")); + marketConfig = await MarketConfig.at(marketConfig); + timeNow = await latestTime(); + + allMarkets = await AllMarkets.at(await masterInstance.getLatestAddress(web3.utils.toHex("AM"))); + marketIncentives = await MarketCreationRewards.at(await masterInstance.getLatestAddress(web3.utils.toHex("MC"))); + await increaseTime(5 * 3600); + await plotusToken.transfer(marketIncentives.address,toWei(100000)); + await plotusToken.transfer(users[11],toWei(100000)); + await plotusToken.transfer(users[12],toWei(100000)); + await plotusToken.approve(tokenController.address,toWei(200000),{from:users[11]}); + await tokenController.lock(toHex("SM"),toWei(25001),30*3600*24,{from:users[11]}); + + let nullAddress = "0x0000000000000000000000000000"; + + await allMarkets.createMarket(0, 0,{from:users[11],gasPrice:500000}); + // await marketIncentives.claimCreationReward(100,{from:users[11]}); + }); + + it("Scenario 3: All winners, no losers", async () => { + let i; + let totalDepositedPlot = toWei(1000); + let predictionVal = [0,100, 400, 210, 123, 500, 700, 200, 50, 300, 150]; + let winningOption =1; + for(i=1; i<11;i++){ + await plotusToken.transfer(users[i], toWei(2000)); + await plotusToken.approve(allMarkets.address, toWei(100000), { from: users[i] }); + let functionSignature = encode3("depositAndPlacePrediction(uint,uint,address,uint64,uint256)", totalDepositedPlot, 7, plotusToken.address, predictionVal[i]*1e8, winningOption); + await marketConfig.setNextOptionPrice(winningOption*9); + await signAndExecuteMetaTx( + privateKeyList[i], + users[i], + functionSignature, + allMarkets, + "AM" + ); + } + + let relayerBalBefore = await plotusToken.balanceOf(users[0]); + await allMarkets.claimRelayerRewards(); + let relayerBalAfter = await plotusToken.balanceOf(users[0]); + + assert.equal(Math.round((relayerBalAfter-relayerBalBefore)/1e15),49.194*1e3); + + + let betpoints = [0,10888.88888, 43555.55555, 22866.66666, 13393.33333, 54444.44444, 76222.22222, 21777.77777, 5444.44444, 32666.66666, 16333.33333]; + + + for(i=1;i<11;i++) + { + let betPointUser = (await allMarkets.getUserPredictionPoints(users[i],7,winningOption))/1e5; + assert.equal(betPointUser,betpoints[i]); + let unusedBal = await allMarkets.getUserUnusedBalance(users[i]); + assert.equal(totalDepositedPlot/1e18-unusedBal[0]/1e18,predictionVal[i]); + } + + await increaseTime(8*60*60); + + await allMarkets.postResultMock(1,7); + await plotusToken.transfer(users[12], "700000000000000000000"); + await plotusToken.approve(allMarkets.address, "500000000000000000000", { + from: users[12], + }); + let proposalId = await governance.getProposalLength(); + await allMarkets.raiseDispute(7, "500000000000000000000","","","", {from: users[12]}); + await increaseTime(604810); + await governance.closeProposal(proposalId/1); + + await increaseTime(60*61); + + let userRewardPlot = [0,98, 392, 205.8, 120.54, 490, 686, 196, 49, 294, 147]; + + for(i=1;i<11;i++) + { + let reward = await allMarkets.getReturn(users[i],7); + assert.equal(Math.round(reward/1e2),userRewardPlot[i]*1e6); + let plotBalBefore = await plotusToken.balanceOf(users[i]); + let plotEthUnused = await allMarkets.getUserUnusedBalance(users[i]); + functionSignature = encode3("withdraw(uint,uint)", plotEthUnused[0].iadd(plotEthUnused[1]), 100); + await signAndExecuteMetaTx( + privateKeyList[i], + users[i], + functionSignature, + allMarkets, + "AM" + ); + let plotBalAfter = await plotusToken.balanceOf(users[i]); + assert.equal(Math.round((plotBalAfter-plotBalBefore)/1e18),Math.round((totalDepositedPlot/1e18-predictionVal[i])/1+reward/1e8)); + } + + let marketCreatorReward = await marketIncentives.getPendingMarketCreationRewards(users[11]); + assert.equal(0,Math.round(marketCreatorReward[1]/1e11)); + + let plotBalBeforeCreator = await plotusToken.balanceOf(users[11]); + + await assertRevert(marketIncentives.claimCreationReward(100,{from:users[11]})); + + let plotBalAfterCreator = await plotusToken.balanceOf(users[11]); + + assert.equal(Math.round((plotBalAfterCreator-plotBalBeforeCreator)/1e11),0); + + + }); + }); + + describe("Scenario5", async () => { + it("Create new market", async () => { + await plotusToken.transfer(users[12],toWei(300000)); + await plotusToken.approve(tokenController.address,toWei(300000),{from:users[12]}); + await tokenController.lock(toHex("SM"),toWei(300000),30*3600*24,{from:users[12]}); + await allMarkets.createMarket(0, 0,{from:users[12], gasPrice:10}); + await plotusToken.transfer(marketIncentives.address,toWei(100000)); + // await marketIncentives.claimCreationReward(100,{from:users[12]}); + }); + + it("Scenario 5: All losers, no winners and Staked less than 1 ETH", async () => { + let i; + let totalDepositedPlot = toWei(1000); + let predictionVal = [0,20,50,100,70,30,100]; + let options=[0,2,3,2,3,3,2]; + for(i=1; i<7;i++){ + await plotusToken.transfer(users[i], toWei(2000)); + await plotusToken.approve(allMarkets.address, toWei(100000), { from: users[i] }); + let functionSignature = encode3("depositAndPlacePrediction(uint,uint,address,uint64,uint256)", totalDepositedPlot, 8, plotusToken.address, predictionVal[i]*1e8, options[i]); + await marketConfig.setNextOptionPrice(options[i]*9); + await signAndExecuteMetaTx( + privateKeyList[i], + users[i], + functionSignature, + allMarkets, + "AM" + ); + } + + let relayerBalBefore = await plotusToken.balanceOf(users[0]); + await allMarkets.claimRelayerRewards(); + let relayerBalAfter = await plotusToken.balanceOf(users[0]); + + assert.equal(Math.round((relayerBalAfter-relayerBalBefore)/1e15),6.66*1e3); + + let betpoints = [0,1088.88888, 1814.81481, 5444.44444, 2540.74074, 1088.88888, 5444.44444]; + + + for(i=1;i<7;i++) + { + let betPointUser = (await allMarkets.getUserPredictionPoints(users[i],8,options[i]))/1e5; + assert.equal(betPointUser,betpoints[i]); + let unusedBal = await allMarkets.getUserUnusedBalance(users[i]); + assert.equal(totalDepositedPlot/1e18-unusedBal[0]/1e18,predictionVal[i]); + } + + await increaseTime(8*60*60); + + await allMarkets.postResultMock(1,8); + + await increaseTime(60*60+1); + + + for(i=1;i<7;i++) + { + let reward = await allMarkets.getReturn(users[i],8); + assert.equal(reward/1e8,0); + + let plotBalBefore = await plotusToken.balanceOf(users[i]); + + let pendingData = await allMarkets.getUserUnusedBalance(users[i]); + if(pendingData[0]/1+pendingData[1]>0){ + functionSignature = encode3("withdraw(uint,uint)", pendingData[0].iadd(pendingData[1]), 100); + await signAndExecuteMetaTx( + privateKeyList[i], + users[i], + functionSignature, + allMarkets, + "AM" + ); + } + let plotBalAfter = await plotusToken.balanceOf(users[i]); + assert.equal(Math.round((plotBalAfter-plotBalBefore)/1e18),Math.round((totalDepositedPlot/1e18-predictionVal[i])/1+reward/1e8)); + } + + let marketCreatorReward = await marketIncentives.getPendingMarketCreationRewards(users[12]); + assert.equal(0,marketCreatorReward[1]); + + + + let tx1 = await assertRevert(marketIncentives.claimCreationReward(100,{from:users[12]})); + + }); + }); +}); diff --git a/test/14_plotusWithBlot.js b/test/14_plotusWithBlot.js deleted file mode 100644 index 1f559aa05..000000000 --- a/test/14_plotusWithBlot.js +++ /dev/null @@ -1,364 +0,0 @@ -const { assert } = require("chai"); - -const OwnedUpgradeabilityProxy = artifacts.require("OwnedUpgradeabilityProxy"); -const Market = artifacts.require("MockMarket"); -const Plotus = artifacts.require("MarketRegistry"); -const Master = artifacts.require("Master"); -const MarketConfig = artifacts.require("MockConfig"); -const PlotusToken = artifacts.require("MockPLOT"); -const BLOT = artifacts.require("BLOT"); -const TokenController = artifacts.require("TokenController"); -const MockUniswapRouter = artifacts.require("MockUniswapRouter"); -const BigNumber = require("bignumber.js"); - -const web3 = Market.web3; -const increaseTime = require("./utils/increaseTime.js").increaseTime; -const assertRevert = require("./utils/assertRevert.js").assertRevert; -// get etherum accounts -// swap ether with LOT - -contract("Market", async function([user1, user2, user3, user4, user5, user6, user7, user8, user9, user10]) { - it("Place the prediction with ether", async () => { - masterInstance = await OwnedUpgradeabilityProxy.deployed(); - masterInstance = await Master.at(masterInstance.address); - plotusToken = await PlotusToken.deployed(); - BLOTInstance = await BLOT.at(await masterInstance.getLatestAddress(web3.utils.toHex("BL"))); - MockUniswapRouterInstance = await MockUniswapRouter.deployed(); - plotusNewAddress = await masterInstance.getLatestAddress(web3.utils.toHex("PL")); - tokenController =await TokenController.at(await masterInstance.getLatestAddress(web3.utils.toHex("TC"))); - plotusNewInstance = await Plotus.at(plotusNewAddress); - marketConfig = await plotusNewInstance.marketUtility(); - marketConfig = await MarketConfig.at(marketConfig); - // console.log(await plotusNewInstance.getOpenMarkets()); - openMarkets = await plotusNewInstance.getOpenMarkets(); - - // console.log(`OpenMaket : ${openMarkets["_openMarkets"][0]}`); - - marketInstance = await Market.at(openMarkets["_openMarkets"][0]); - await increaseTime(10001); - assert.ok(marketInstance); - - // setting option price in eth - await marketConfig.setOptionPrice(1, 9); - await marketConfig.setOptionPrice(2, 18); - await marketConfig.setOptionPrice(3, 27); - - await assertRevert(marketInstance.calculatePredictionResult(1)); //should revert as market is in live status - - // set price - // user 1 - // set price lot - await MockUniswapRouterInstance.setPrice("1000000000000000"); - await marketConfig.setPrice("1000000000000000"); - await plotusToken.approve(tokenController.address, "100000000000000000000", { - from: user1, - }); - await marketInstance.placePrediction(plotusToken.address, "100000000000000000000", 2, 1, { from: user1 }); - - // user 2 - await MockUniswapRouterInstance.setPrice("2000000000000000"); - await marketConfig.setPrice("2000000000000000"); - // await plotusToken.transfer(user2, "500000000000000000000"); - - // await plotusToken.approve( - // openMarkets["_openMarkets"][0], - // "400000000000000000000", - // { - // from: user2, - // } - // ); - // await marketInstance.placePrediction( - // plotusToken.address, - // "400000000000000000000", - // 2, - // 2, - // { from: user2 } - // ); - await plotusToken.approve(BLOTInstance.address, "4000000000000000000000"); - await BLOTInstance.mint(user2, "400000000000000000000"); - - // await BLOTInstance.transferFrom(user1, user2, "500000000000000000000", { - // from: user1, - // }); - - // await BLOTInstance.approve(openMarkets["_openMarkets"][0], "400000000000000000000", { - // from: user2, - // }); - // console.log(await BLOTInstance.balanceOf(user1)); - // await BLOTInstance.addMinter(marketInstance.address); - await marketInstance.placePrediction(BLOTInstance.address, "400000000000000000000", 2, 5, { from: user2 }); - let flags = await marketInstance.getUserFlags(user2); - assert.equal(flags[1], true); - // user 3 - await MockUniswapRouterInstance.setPrice("1000000000000000"); - await marketConfig.setPrice("1000000000000000"); - await plotusToken.transfer(user3, "500000000000000000000"); - await plotusToken.approve(tokenController.address, "210000000000000000000", { - from: user3, - }); - - await assertRevert(marketInstance.placePrediction(user10, "210000000000000000000", 2, 2, { from: user3 })); //should revert as assert not valid - await assertRevert(marketInstance.placePrediction(plotusToken.address, "210000000000000000000", 2, 2, { from: user3, value: "100" })); // should revert as passing value - await assertRevert(marketInstance.placePrediction(plotusToken.address, "1", 2, 2, { from: user3 })); // should revert as prediction amount is less than min required prediction - // try { - // await marketInstance.placePrediction(plotusToken.address, "600000000000000000000", 2, 2, { from: user3 }); // should revert as user do not have enough asset - // assert.fail(); - // } catch (e) { - // console.log(e); - // } - - await marketInstance.placePrediction(plotusToken.address, "210000000000000000000", 2, 2, { from: user3 }); - // user 4 - await MockUniswapRouterInstance.setPrice("15000000000000000"); - await marketConfig.setPrice("15000000000000000"); - - await plotusToken.approve(BLOTInstance.address, "124000000000000000000"); - await BLOTInstance.mint(user4, "124000000000000000000"); - - // await BLOTInstance.approve(openMarkets["_openMarkets"][0], "124000000000000000000", { - // from: user4, - // }); - - await assertRevert(marketInstance.placePrediction(BLOTInstance.address, "123000000000000000000", 3, 4, { from: user4 })); //should revert as leverage is not 5 - await assertRevert( - marketInstance.placePrediction(BLOTInstance.address, "123000000000000000000", 3, 5, { from: user4, value: "1000000000000000000" }) - ); // should revert as passing value - - await marketInstance.placePrediction(BLOTInstance.address, "123000000000000000000", 3, 5, { from: user4 }); - - await assertRevert(marketInstance.placePrediction(BLOTInstance.address, "1000000000000000000", 3, 5, { from: user4 })); //should revert as once usr can only place Prediction with BLOT once in a market - - // await plotusToken.transfer(user4, "200000000000000000000"); - - // await plotusToken.approve( - // openMarkets["_openMarkets"][0], - // "123000000000000000000", - // { - // from: user4, - // } - // ); - // await marketInstance.placePrediction( - // plotusToken.address, - // "123000000000000000000", - // 3, - // 3, - // { from: user4 } - // ); - - // user 5 - await MockUniswapRouterInstance.setPrice("12000000000000000"); - await marketConfig.setPrice("12000000000000000"); - await assertRevert( - marketInstance.placePrediction("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", "1000000000000000000", 1, 4, { - value: "100000000000000000", - from: user5, - }) - ); - await marketInstance.placePrediction("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", "1000000000000000000", 1, 4, { - value: "1000000000000000000", - from: user5, - }); - - // user 6 - await MockUniswapRouterInstance.setPrice("14000000000000000"); - await marketConfig.setPrice("14000000000000000"); - await marketInstance.placePrediction("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", "2000000000000000000", 1, 5, { - value: "2000000000000000000", - from: user6, - }); - // user 7 - await MockUniswapRouterInstance.setPrice("10000000000000000"); - await marketConfig.setPrice("10000000000000000"); - - await marketInstance.placePrediction("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", "1000000000000000000", 2, 2, { - value: "1000000000000000000", - from: user7, - }); - // user 8 - await MockUniswapRouterInstance.setPrice("45000000000000000"); - await marketConfig.setPrice("45000000000000000"); - await marketInstance.placePrediction("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", "3000000000000000000", 3, 3, { - value: "3000000000000000000", - from: user8, - }); - // user 9 - await MockUniswapRouterInstance.setPrice("51000000000000000"); - await marketConfig.setPrice("51000000000000000"); - await marketInstance.placePrediction("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", "1000000000000000000", 3, 1, { - value: "1000000000000000000", - from: user9, - }); - // user 10 - await MockUniswapRouterInstance.setPrice("12000000000000000"); - await marketConfig.setPrice("12000000000000000"); - await marketInstance.placePrediction("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", "2000000000000000000", 2, 4, { - value: "2000000000000000000", - from: user10, - }); - }); - - it("1.Prediction Points allocated properly in ether", async () => { - accounts = [user1, user2, user3, user4, user5, user6, user7, user8, user9, user10]; - options = [2, 2, 2, 3, 1, 1, 2, 3, 3, 2]; - getPredictionPoints = async (user, option, expected) => { - // return Prediction points of user - let PredictionPoins = await marketInstance.getUserPredictionPoints(user, option); - PredictionPoins = PredictionPoins / 1; - return PredictionPoins; - }; - PredictionPointsExpected = [1.755503471, 238.3350545, 11.21889102, 556.4885586, 510.3, 1882.8, 116.5, 634.1, 37.0, 721.7]; - - // console.log("Prediction points for user 1"); - // PredictionPointsUser1 = await getPredictionPoints(accounts[0], options[0]); - // PredictionPointsUser3 = await getPredictionPoints(accounts[2], options[2]); - - // console.log( - // `Prediction points : ${PredictionPointsUser1} expected : ${PredictionPointsExpected[0]} ` - // ); - // console.log("Prediction points for user 3"); - // console.log( - // `Prediction points : ${PredictionPointsUser3} expected : ${PredictionPointsExpected[2]} ` - // ); - for (let index = 0; index < 10; index++) { - let PredictionPoints = await getPredictionPoints(accounts[index], options[index]); - PredictionPoints = PredictionPoints / 1000; - PredictionPoints = PredictionPoints.toFixed(1); - assert.equal(PredictionPoints, PredictionPointsExpected[index].toFixed(1)); - // commented by parv (as already added assert above) - // console.log(`user${index + 1} : option : ${options[index]} `); - // console.log(`Prediction points : ${PredictionPoints} expected : ${PredictionPointsExpected[index].toFixed(1)} `); - } - // console.log(await plotusToken.balanceOf(user1)); - - // close market - await increaseTime(36001); - await marketInstance.calculatePredictionResult(1); - await increaseTime(36001); - // console.log((await web3.eth.getBalance(marketInstance.address))/1) - // plotus contract balance eth balance - plotusBalanceBefore = await web3.eth.getBalance(plotusNewAddress); - assert.equal(parseFloat(plotusBalanceBefore), "10000000000000000"); - lotBalanceBefore = await plotusToken.balanceOf(openMarkets["_openMarkets"][0]); - assert.equal(parseFloat(web3.utils.fromWei(lotBalanceBefore)).toFixed(2), (832.5835).toFixed(2)); - - // lot supply , lot balance of market - await MockUniswapRouterInstance.setPrice("1000000000000000"); - await marketConfig.setPrice("1000000000000000"); - - - plotusBalanceAfter = await web3.eth.getBalance(plotusNewAddress); - assert.equal(parseFloat(plotusBalanceAfter), 10000000000000000); - lotBalanceAfter = await plotusToken.balanceOf(openMarkets["_openMarkets"][0]); - assert.equal(parseFloat(web3.utils.fromWei(lotBalanceAfter)).toFixed(2), (832.5835).toFixed(2)); - // assert.equal(parseFloat(web3.utils.fromWei(String(parseFloat(lotBalanceAfter) - parseFloat(lotBalanceBefore)))).toFixed(2), (4.5835).toFixed(2)); - // commented by Parv (as asserts already added above) - // lotBalanceBefore = lotBalanceBefore / 1; - // lotBalanceAfter = lotBalanceAfter / 1; - // console.log(`plotus eth balance before commision : ${plotusBalanceBefore}`); - // console.log(`plotus balance after commision : ${plotusBalanceAfter}`); - // console.log(`Lot Balance of market before commision : ${lotBalanceBefore}`); - // console.log(`Lot Balance of market before commision : ${lotBalanceAfter}`); - // console.log(`Difference : ${lotBalanceAfter - lotBalanceBefore}`); - }); - - it("2.check total return for each user Prediction values in eth", async () => { - accounts = [user1, user2, user3, user4, user5, user6, user7, user8, user9, user10]; - options = [2, 2, 2, 3, 1, 1, 2, 3, 3, 2]; - getReturnsInEth = async (user) => { - // return userReturn in eth - const response = await marketInstance.getReturn(user); - let returnAmountInEth = web3.utils.fromWei(response[0][1]); - return returnAmountInEth; - }; - - const returnInEthExpected = [0, 0, 0, 0, 1.851161356, 5.141838644, 0.5994, 1.1988, 0.7992, 0.3996]; - // calulate rewards for every user in eth - - // console.log("Rewards in Eth"); - for (let index = 0; index < 10; index++) { - // check eth returns - let returns = await getReturnsInEth(accounts[index]); - assert.equal(parseFloat(returns).toFixed(2), returnInEthExpected[index].toFixed(2)); - // commented by Parv (as assert already added above) - // console.log(`return : ${returns} Expected :${returnInEthExpected[index]}`); - } - }); - it("3.Check User Recived The appropriate amount", async () => { - accounts = [user1, user2, user3, user4, user5, user6, user7, user8, user9, user10]; - const totalReturnLotExpexted = [79.96, 0, 125.937, 0, 133.6431475, 493.0463525, 0, 0, 0, 0]; - const returnInEthExpected = [0, 0, 0, 0, 1.851161356, 5.141838644, 0.5994, 1.1988, 0.7992, 0.3996]; - for (let account of accounts) { - beforeClaim = await web3.eth.getBalance(account); - beforeClaimToken = await plotusToken.balanceOf(account); - await marketInstance.claimReturn(account); - afterClaim = await web3.eth.getBalance(account); - afterClaimToken = await plotusToken.balanceOf(account); - diff = afterClaim - beforeClaim; - diff = new BigNumber(diff); - conv = new BigNumber(1000000000000000000); - diff = diff / conv; - diff = diff.toFixed(2); - // expectedInEth = returnInEthExpected[accounts.indexOf(account)].toFixed(2); - // assert.equal(diff, expectedInEth); - - diffToken = afterClaimToken - beforeClaimToken; - diffToken = diffToken / conv; - diffToken = diffToken.toFixed(2); - expectedInLot = totalReturnLotExpexted[accounts.indexOf(account)].toFixed(2); - assert.equal(diffToken, expectedInLot); - - // commented by Parv (as assert already added above) - // console.log(`User ${accounts.indexOf(account) + 1}`); - // console.log(`Returned in Eth : ${diff} Expected : ${expectedInEth} `); - // console.log(`Returned in Lot : ${diffToken} Expected : ${expectedInLot} `); - } - }); -}); -contract("Market", async function([user1, user2]) { - let masterInstance, BLOTInstance; - it("Test BLOT Contract", async () => { - masterInstance = await OwnedUpgradeabilityProxy.deployed(); - masterInstance = await Master.at(masterInstance.address); - plotusToken = await PlotusToken.deployed(); - BLOTInstance = await BLOT.at(await masterInstance.getLatestAddress(web3.utils.toHex("BL"))); - MockUniswapRouterInstance = await MockUniswapRouter.deployed(); - plotusNewAddress = await masterInstance.getLatestAddress(web3.utils.toHex("PL")); - plotusNewInstance = await Plotus.at(plotusNewAddress); - marketConfig = await plotusNewInstance.marketUtility(); - marketConfig = await MarketConfig.at(marketConfig); - // console.log(await plotusNewInstance.getOpenMarkets()); - - // let operatorNow = await BLOTInstance.operator(); - // assert.equal(operatorNow, "0x0000000000000000000000000000000000000000"); - - // let receipt = await BLOTInstance.changeOperator.call(user1); - // operatorNow = await BLOTInstance.operator(); - // assert.equal(receipt, true); - // assert.equal(operatorNow, user1); - - let isMinter = await BLOTInstance.isMinter(user1); - // assert.equal(isMinter, false); - // isMinter = await BLOTInstance.isMinter(user1); - assert.equal(isMinter, true); - - isMinter = await BLOTInstance.isMinter(user2); - assert.equal(isMinter, false); - receipt = await BLOTInstance.addMinter(user2); - isMinter = await BLOTInstance.isMinter(user2); - assert.equal(isMinter, true); - assert.equal(receipt.logs[0].event, "MinterAdded"); - assert.equal(receipt.logs[0].args.account, user2); - - receipt = await BLOTInstance.renounceMinter({ from: user2 }); - isMinter = await BLOTInstance.isMinter(user2); - assert.equal(isMinter, false); - assert.equal(receipt.logs[0].event, "MinterRemoved"); - assert.equal(receipt.logs[0].args.account, user2); - - await assertRevert(BLOTInstance.mint(user2, 100)); - try { - await BLOTInstance.transfer("0x0000000000000000000000000000000000000000", 10, { from: user1 }); - assert.fail(); - } catch (e) {} - }); -}); diff --git a/test/15_allMarkets.test.js b/test/15_allMarkets.test.js new file mode 100644 index 000000000..869c41105 --- /dev/null +++ b/test/15_allMarkets.test.js @@ -0,0 +1,617 @@ +const OwnedUpgradeabilityProxy = artifacts.require("OwnedUpgradeabilityProxy"); +const Governance = artifacts.require("Governance"); +const MemberRoles = artifacts.require("MemberRoles"); +const ProposalCategory = artifacts.require("ProposalCategory"); +const TokenController = artifacts.require("TokenController"); +const NXMaster = artifacts.require("Master"); +const AllMarkets = artifacts.require("MockAllMarkets"); +const MarketCreationRewards = artifacts.require('MarketCreationRewards'); +const MockChainLinkGasPriceAgg = artifacts.require("MockChainLinkGasPriceAgg"); +const MarketConfig = artifacts.require("MockConfig"); +const PlotusToken = artifacts.require("MockPLOT"); +const MockchainLink = artifacts.require("MockChainLinkAggregator"); +const assertRevert = require("./utils/assertRevert.js").assertRevert; +const increaseTime = require("./utils/increaseTime.js").increaseTime; +const latestTime = require("./utils/latestTime.js").latestTime; +const encode = require("./utils/encoder.js").encode; +const encode1 = require("./utils/encoder.js").encode1; +const { toHex, toWei } = require("./utils/ethTools.js"); +const expectEvent = require("./utils/expectEvent"); +const gvProp = require("./utils/gvProposal.js").gvProposal; +// const Web3 = require("web3"); +const { assert } = require("chai"); +// const gvProposalWithIncentive = require("./utils/gvProposal.js").gvProposalWithIncentive; +const gvProposal = require("./utils/gvProposal.js").gvProposalWithIncentiveViaTokenHolder; +// const web3 = new Web3(); +const AdvisoryBoard = "0x41420000"; +let maxAllowance = "115792089237316195423570985008687907853269984665640564039457584007913129639935"; + +let gv; +let cr; +let pc; +let nxms; +let proposalId; +let pId; +let mr; +let plotusToken; +let tc; +let td; +let pl; +let mockchainLinkInstance; +let allMarkets, marketIncentives, tokenController; +let nullAddress = "0x0000000000000000000000000000000000000000"; + +contract("PlotX", ([ab1, ab2, ab3, ab4, mem1, mem2, mem3, mem4, mem5, mem6, mem7, mem8, mem9, mem10, notMember, dr1, dr2, dr3, user11, user12, user13, user14]) => { + before(async function() { + nxms = await OwnedUpgradeabilityProxy.deployed(); + nxms = await NXMaster.at(nxms.address); + plotusToken = await PlotusToken.deployed(); + let address = await nxms.getLatestAddress(toHex("GV")); + gv = await Governance.at(address); + address = await nxms.getLatestAddress(toHex("PC")); + pc = await ProposalCategory.at(address); + address = await nxms.getLatestAddress(toHex("MR")); + mr = await MemberRoles.at(address); + mockchainLinkInstance = await MockchainLink.deployed(); + marketConfig = await nxms.getLatestAddress(toHex("MU")); + marketConfig = await MarketConfig.at(marketConfig); + tc = await TokenController.at(await nxms.getLatestAddress(toHex("TC"))); + + governance = await nxms.getLatestAddress(toHex("GV")); + governance = await Governance.at(governance); + tokenController =await TokenController.at(await nxms.getLatestAddress(toHex("TC"))); + marketConfig = await MarketConfig.at(marketConfig.address); + let date = await latestTime(); + await increaseTime(3610); + date = Math.round(date); + // await marketConfig.setInitialCummulativePrice(); + allMarkets = await AllMarkets.at(await nxms.getLatestAddress(toHex("AM"))); + marketIncentives = await MarketCreationRewards.at(await nxms.getLatestAddress(toHex("MC"))); + await assertRevert(marketIncentives.setMasterAddress()); + // await assertRevert(marketIncentives.initialise(marketConfig.address, mockchainLinkInstance.address)); + await increaseTime(5 * 3600); + await plotusToken.transfer(marketIncentives.address,toWei(100000)); + await plotusToken.transfer(user11,toWei(100000)); + await plotusToken.transfer(user12,toWei(100000)); + await plotusToken.transfer(user14,toWei(100000)); + await plotusToken.approve(tokenController.address,toWei(200000),{from:user11}); + await tokenController.lock(toHex("SM"),toWei(100000),30*3600*24,{from:user11}); + + await plotusToken.transfer(mem1, toWei(100)); + await plotusToken.transfer(mem2, toWei(100)); + await plotusToken.transfer(mem3, toWei(100)); + await plotusToken.transfer(mem4, toWei(100)); + await plotusToken.transfer(mem5, toWei(100)); + + }); + + it("Should create a proposal to whitelist sponsor", async function() { + await increaseTime(604810); + pId = (await gv.getProposalLength()).toNumber(); + await gv.createProposal("Proposal2", "Proposal2", "Proposal2", 0); //Pid 3 + await gv.categorizeProposal(pId, 21, 0); + let startTime = (await latestTime()) / 1 + 2 * 604800; + let actionHash = encode("whitelistSponsor(address)", ab1); + await gv.submitProposalWithSolution(pId, "whitelistSponsor", actionHash); + await gv.submitVote(pId, 1, { from: ab1 }); + // let canClose = await gv.canCloseProposal(pId); + //assert.equal(canClose.toNumber(), 1); + await increaseTime(604810); + await assertRevert(gv.submitVote(pId, 1, { from: mem2 })); //closed to vote + await gv.closeProposal(pId); + let actionStatus = await gv.proposalActionStatus(pId); + assert.equal(actionStatus / 1, 3); + }); + + it("Should not add new market curreny if already exists", async function() { + await increaseTime(604810); + pId = (await gv.getProposalLength()).toNumber(); + await gv.createProposal("Proposal2", "Proposal2", "Proposal2", 0); //Pid 3 + await gv.categorizeProposal(pId, 15, 0); + let startTime = (await latestTime()) / 1 + 2 * 604800; + let actionHash = encode("addMarketCurrency(bytes32,address,uint8,uint8,uint32)", toHex("ETH/USD"), mockchainLinkInstance.address, 8, 1, startTime); + await gv.submitProposalWithSolution(pId, "addNewMarketCurrency", actionHash); + await gv.submitVote(pId, 1, { from: ab1 }); + await increaseTime(604810); + await assertRevert(gv.submitVote(pId, 1, { from: mem2 })); //closed to vote + await gv.closeProposal(pId); + let actionStatus = await gv.proposalActionStatus(pId); + assert.equal(actionStatus / 1, 1); + }); + + it("Should not add new market curreny if decimals passed is zero", async function() { + await increaseTime(604810); + pId = (await gv.getProposalLength()).toNumber(); + await gv.createProposal("Proposal2", "Proposal2", "Proposal2", 0); //Pid 3 + await gv.categorizeProposal(pId, 15, 0); + let startTime = (await latestTime()) / 1 + 2 * 604800; + let actionHash = encode("addMarketCurrency(bytes32,address,uint8,uint8,uint32)", toHex("ETH/PLOT"), mockchainLinkInstance.address, 0, 1, startTime); + await gv.submitProposalWithSolution(pId, "addNewMarketCurrency", actionHash); + await gv.submitVote(pId, 1, { from: ab1 }); + await increaseTime(604810); + await assertRevert(gv.submitVote(pId, 1, { from: mem2 })); //closed to vote + await gv.closeProposal(pId); + let actionStatus = await gv.proposalActionStatus(pId); + assert.equal(actionStatus / 1, 1); + }); + + it("Should not add new market curreny if round off argument passed is zero", async function() { + await increaseTime(604810); + pId = (await gv.getProposalLength()).toNumber(); + await gv.createProposal("Proposal2", "Proposal2", "Proposal2", 0); //Pid 3 + await gv.categorizeProposal(pId, 15, 0); + let startTime = (await latestTime()) / 1 + 2 * 604800; + let actionHash = encode("addMarketCurrency(bytes32,address,uint8,uint8,uint32)", toHex("ETH/PLOT"), mockchainLinkInstance.address, 8, 0, startTime); + await gv.submitProposalWithSolution(pId, "addNewMarketCurrency", actionHash); + await gv.submitVote(pId, 1, { from: ab1 }); + await increaseTime(604810); + await assertRevert(gv.submitVote(pId, 1, { from: mem2 })); //closed to vote + await gv.closeProposal(pId); + let actionStatus = await gv.proposalActionStatus(pId); + assert.equal(actionStatus / 1, 1); + }); + + it("Should create a proposal to add new market curreny", async function() { + await increaseTime(604810); + pId = (await gv.getProposalLength()).toNumber(); + await gv.createProposal("Proposal2", "Proposal2", "Proposal2", 0); //Pid 3 + await gv.categorizeProposal(pId, 15, 0); + let startTime = (await latestTime()) / 1 + 2 * 604800; + let actionHash = encode("addMarketCurrency(bytes32,address,uint8,uint8,uint32)", toHex("ETH/PLOT"), mockchainLinkInstance.address, 8, 1, startTime); + await gv.submitProposalWithSolution(pId, "addNewMarketCurrency", actionHash); + await gv.submitVote(pId, 1, { from: ab1 }); + await increaseTime(604810); + await assertRevert(gv.submitVote(pId, 1, { from: mem2 })); //closed to vote + await gv.closeProposal(pId); + let actionStatus = await gv.proposalActionStatus(pId); + assert.equal(actionStatus / 1, 3); + await plotusToken.approve(allMarkets.address, toWei(1000000), {from:user14}); + await increaseTime(604810); + await allMarkets.createMarket(2,0,{from:user14}); + }); + + it("Predict on newly created market", async function() { + await marketConfig.setNextOptionPrice(18); + + // set price + // user 1 + // set price lot + await marketConfig.setPrice("1000000000000000"); + await plotusToken.approve(allMarkets.address, "18000000000000000000000000"); + await plotusToken.approve(allMarkets.address, "18000000000000000000000000", {from:mem1}); + await plotusToken.approve(allMarkets.address, "18000000000000000000000000"); + await allMarkets.depositAndPlacePrediction("100000000000000000000", 7, plotusToken.address, 100*1e8, 1); + // await allMarkets.placePrediction(plotusToken.address, "1000000000000000000000", 1, 1); + let totalStaked = await allMarkets.getUserFlags(7, ab1); + assert.equal(totalStaked[0], false); + await allMarkets.depositAndPlacePrediction("8000000000000000000000", 7, plotusToken.address, 8000*1e8, 2); + await allMarkets.depositAndPlacePrediction("8000000000000000000000", 7, plotusToken.address, 8000*1e8, 3); + // await assertRevert(marketInstance.placePrediction("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", "10000000000000000000", 1, 1, { value: 1000 })); + // await assertRevert(allMarkets.settleMarket(7)); + await assertRevert(allMarkets.postResultMock(0,7)); + await increaseTime(604810); + // await allMarkets.withdrawMax(100); + // await marketInstance.claimReturn(ab1); + await allMarkets.postResultMock(1, 7); + // await assertRevert(marketInstance.placePrediction(plotusToken.address, "10000000000000000000", 1, 1)); + await increaseTime(604800); + let balance = await allMarkets.getUserUnusedBalance(ab1); + await allMarkets.withdraw((balance[1]), 100); + // await marketInstance.claimReturn(ab1); + await increaseTime(604800); + }); + + it("Should not add new market type if prediction type already exists", async function() { + await increaseTime(604810); + pId = (await gv.getProposalLength()).toNumber(); + await gv.createProposal("Proposal2", "Proposal2", "Proposal2", 0); //Pid 3 + await gv.categorizeProposal(pId, 14, 0); + let startTime = Math.round(Date.now()); + startTime = (await latestTime()) / 1 + 3 * 604800; + let actionHash = encode("addMarketType(uint32,uint32,uint32,uint32,uint32)", 24 * 60 * 60, 50, startTime, 3600, 100); + await gv.submitProposalWithSolution(pId, "update max followers limit", actionHash); + await gv.submitVote(pId, 1, { from: ab1 }); + await increaseTime(604810); + await gv.closeProposal(pId); + let actionStatus = await gv.proposalActionStatus(pId); + assert.equal(actionStatus / 1, 1); + }); + + it("Should not add new market type if prediction is zero", async function() { + await increaseTime(604810); + pId = (await gv.getProposalLength()).toNumber(); + await gv.createProposal("Proposal2", "Proposal2", "Proposal2", 0); //Pid 3 + await gv.categorizeProposal(pId, 14, 0); + let startTime = Math.round(Date.now()); + startTime = (await latestTime()) / 1 + 3 * 604800; + let actionHash = encode("addMarketType(uint32,uint32,uint32,uint32,uint32)", 0, 50, startTime, 3600, 100); + await gv.submitProposalWithSolution(pId, "update max followers limit", actionHash); + await gv.submitVote(pId, 1, { from: ab1 }); + await increaseTime(604810); + await gv.closeProposal(pId); + let actionStatus = await gv.proposalActionStatus(pId); + assert.equal(actionStatus / 1, 1); + }); + + it("Should not add new market type if option range percent is zero", async function() { + await increaseTime(604810); + pId = (await gv.getProposalLength()).toNumber(); + await gv.createProposal("Proposal2", "Proposal2", "Proposal2", 0); //Pid 3 + await gv.categorizeProposal(pId, 14, 0); + let startTime = Math.round(Date.now()); + startTime = (await latestTime()) / 1 + 3 * 604800; + let actionHash = encode("addMarketType(uint32,uint32,uint32,uint32,uint32)", 6 * 60 * 60, 0, startTime, 3600, 100); + await gv.submitProposalWithSolution(pId, "update max followers limit", actionHash); + await gv.submitVote(pId, 1, { from: ab1 }); + await increaseTime(604810); + await gv.closeProposal(pId); + let actionStatus = await gv.proposalActionStatus(pId); + assert.equal(actionStatus / 1, 1); + }); + + it("Should create a proposal to add new market type", async function() { + await increaseTime(604810); + pId = (await gv.getProposalLength()).toNumber(); + await gv.createProposal("Proposal2", "Proposal2", "Proposal2", 0); //Pid 3 + await gv.categorizeProposal(pId, 14, 0); + let startTime = Math.round(Date.now()); + startTime = (await latestTime()) / 1 + 3 * 604800; + // startTime = Math.round((Date.now())/1000) + 2*604800; + let actionHash = encode("addMarketType(uint32,uint32,uint32,uint32,uint32)", 60 * 60, 50, startTime, 7200, 100); + await gv.submitProposalWithSolution(pId, "update max followers limit", actionHash); + + actionHash = encode("addMarketType(uint32,uint32,uint32,uint32,uint32)", 60 * 60 * 2, 1, 10, 3600, 100); + await assertRevert(gv.submitProposalWithSolution(pId, "update max followers limit", actionHash)); //should revert as start time is not enough + actionHash = encode("addMarketType(uint32,uint32,uint32,uint32,uint32)", 60 * 60 * 2, await latestTime(),10, 3600, 100); + await assertRevert(gv.submitProposalWithSolution(pId, "update max followers limit", actionHash)); //should revert as start time is not enough + + await gv.submitVote(pId, 1, { from: ab1 }); + await assertRevert(gv.triggerAction(pId)); //cannot trigger + await increaseTime(604810); + await assertRevert(gv.triggerAction(pId)); //cannot trigger + await gv.closeProposal(pId); + let actionStatus = await gv.proposalActionStatus(pId); + assert.equal(actionStatus / 1, 3); + let solutionAction = await gv.getSolutionAction(pId, 1); + assert.equal(parseFloat(solutionAction[0]), 1); + let voteData = await gv.voteTallyData(pId, 1); + assert.equal(parseFloat(voteData[0]), 1); + // assert.equal(parseFloat(voteData[0]), 1.50005e+25); + // assert.equal(parseFloat(voteData[1]), 1); + // assert.equal(parseFloat(voteData[2]), 6); + await increaseTime(604810); + await increaseTime(604820); + await allMarkets.createMarket(0,3, {from:user14}); + + // let openMarkets = await pl.getOpenMarkets(); + // assert.isAbove(openMarkets[1].length, openMarketsBefore[1].length, "Currency not added"); + }); + + it("Predict on newly created market", async function() { + await marketConfig.setNextOptionPrice(18); + await assertRevert(allMarkets.createMarket(0,3), {from:user14}); //should revert as market is live + // await increaseTime(604820); + + // set price + // user 1 + // set price lot + await marketConfig.setPrice("1000000000000000"); + await plotusToken.approve(allMarkets.address, "1000000000000000000000"); + await allMarkets.depositAndPlacePrediction("100000000000000000000", 8, plotusToken.address, 100*1e8, 1); + let reward = await allMarkets.getReturn(ab1, 8); + assert.equal(reward, 0); + await increaseTime(3650); + await allMarkets.createMarket(0, 3, {from:user14}); + await increaseTime(604810); + await allMarkets.settleMarket(8); + let marketSettleTime = await allMarkets.marketSettleTime(8); + let marketCoolDownTime = await allMarkets.marketCoolDownTime(8); + assert.equal(marketCoolDownTime/1 - marketSettleTime/1, 7200); + await allMarkets.settleMarket(9); + await allMarkets.createMarket(0, 3); + await increaseTime(604800); + await allMarkets.createMarket(0, 3); + // await pl.exchangeCommission(marketInstance.address); + await allMarkets.getMarketData(8); + }); + + it("Pause market creation ", async function() { + await allMarkets.createMarket(0, 1); + await assertRevert(allMarkets.createMarket(0, 1)); + pId = (await gv.getProposalLength()).toNumber(); + await gvProposal(16, "0x", await MemberRoles.at(await nxms.getLatestAddress(toHex("MR"))), gv, 2, 0); + let actionStatus = await gv.proposalActionStatus(pId); + assert.equal(actionStatus / 1, 3); + await increaseTime(604800); + await assertRevert(allMarkets.createMarket(0, 1)); + let balance = await allMarkets.getUserUnusedBalance(ab1); + balance = (balance[0]/1+balance[1]/1); + await assertRevert(allMarkets.withdraw(toWei(balance/1e18), 100)); + }); + + it("Cannot Pause market creation if already paused", async function() { + await assertRevert(allMarkets.createMarket(0, 1)); + pId = (await gv.getProposalLength()).toNumber(); + await gvProposal(16, "0x", await MemberRoles.at(await nxms.getLatestAddress(toHex("MR"))), gv, 2, 0); + let actionStatus = await gv.proposalActionStatus(pId); + assert.equal(actionStatus / 1, 1); + await increaseTime(604800); + }); + + it("Resume market creation ", async function() { + await assertRevert(allMarkets.createMarket(0, 1)); + pId = (await gv.getProposalLength()).toNumber(); + await gvProposal(17, "0x", await MemberRoles.at(await nxms.getLatestAddress(toHex("MR"))), gv, 2, 0); + let actionStatus = await gv.proposalActionStatus(pId); + assert.equal(actionStatus / 1, 3); + await increaseTime(604800); + await allMarkets.createMarket(0, 1); + let balance = await allMarkets.getUserUnusedBalance(ab1); + balance = (balance[0]/1+balance[1]/1); + if(balance > 0) { + await allMarkets.withdraw(toWei(balance/1e18), 100); + } + await assertRevert(allMarkets.withdraw(toWei(balance/1e18), 100)); + + // await allMarkets.withdrawReward(100); + // await allMarkets.withdrawReward(100); + }); + + it("Cannot Resume market creation if already live ", async function() { + await increaseTime(86401); + await allMarkets.createMarket(0, 1); + pId = (await gv.getProposalLength()).toNumber(); + await gvProposal(17, "0x", await MemberRoles.at(await nxms.getLatestAddress(toHex("MR"))), gv, 2, 0); + let actionStatus = await gv.proposalActionStatus(pId); + assert.equal(actionStatus / 1, 1); + }); + + it("Pause market creation of 4-hourly markets", async function() { + await allMarkets.createMarket(0, 0); + pId = (await gv.getProposalLength()).toNumber(); + let categoryId = await pc.totalCategories(); + categoryId = 22; + let actionHash = encode1(["uint64","bool"],[0,true]) + await gvProposal(categoryId, actionHash, await MemberRoles.at(await nxms.getLatestAddress(toHex("MR"))), gv, 2, 0); + let actionStatus = await gv.proposalActionStatus(pId); + assert.equal(actionStatus / 1, 3); + await increaseTime(604800); + await assertRevert(allMarkets.createMarket(0, 0)); + await allMarkets.createMarket(0, 1); + }); + + it("Resume market creation of 4-hourly markets", async function() { + await increaseTime(604800); + await assertRevert(allMarkets.createMarket(0, 0)); + pId = (await gv.getProposalLength()).toNumber(); + let categoryId = await pc.totalCategories(); + categoryId = 22; + let actionHash = encode1(["uint64","bool"],[0,false]) + await gvProposal(categoryId, actionHash, await MemberRoles.at(await nxms.getLatestAddress(toHex("MR"))), gv, 2, 0); + let actionStatus = await gv.proposalActionStatus(pId); + assert.equal(actionStatus / 1, 3); + await increaseTime(604800); + await allMarkets.createMarket(0, 0); + await allMarkets.createMarket(0, 1); + await increaseTime(604800); + }); + + it("Cannot Resume market creation of 4-hourly markets if already live", async function() { + await increaseTime(604800); + await allMarkets.createMarket(0, 0); + pId = (await gv.getProposalLength()).toNumber(); + let categoryId = await pc.totalCategories(); + categoryId = 22; + let actionHash = encode1(["uint64","bool"],[0,false]) + await gvProposal(categoryId, actionHash, await MemberRoles.at(await nxms.getLatestAddress(toHex("MR"))), gv, 2, 0); + let actionStatus = await gv.proposalActionStatus(pId); + assert.equal(actionStatus / 1, 1); + await increaseTime(604800); + await allMarkets.createMarket(0, 0); + await marketIncentives.getPendingMarketCreationRewards(ab1); + await allMarkets.createMarket(0, 1); + await increaseTime(604800); + }); + + it("Transfer DAO plot through proposal", async function() { + await increaseTime(604800); + pId = (await gv.getProposalLength()).toNumber(); + let categoryId = 18; + await plotusToken.transfer(marketIncentives.address, toWei(100)); + let daoPLOTbalanceBefore = await plotusToken.balanceOf(marketIncentives.address); + let userPLOTbalanceBefore = await plotusToken.balanceOf(user11); + let actionHash = encode1(["address","address","uint256"],[plotusToken.address, user11, toWei(100)]) + await gvProposal(categoryId, actionHash, await MemberRoles.at(await nxms.getLatestAddress(toHex("MR"))), gv, 2, 0); + let actionStatus = await gv.proposalActionStatus(pId); + assert.equal(actionStatus / 1, 3); + let daoPLOTbalanceAfter = await plotusToken.balanceOf(marketIncentives.address); + let userPLOTbalanceAfter = await plotusToken.balanceOf(user11); + assert.equal((daoPLOTbalanceBefore/1e18 - 100).toFixed(2), (daoPLOTbalanceAfter/1e18).toFixed(2)); + assert.equal((userPLOTbalanceBefore/1e18 + 100).toFixed(2), (userPLOTbalanceAfter/1e18).toFixed(2)); + await increaseTime(604800); + }); + + it("Add category to update uint paramters of MarketCreationRewards", async function() { + let actionHash = encode1( + ["string", "uint256", "uint256", "uint256", "uint256[]", "uint256", "string", "address", "bytes2", "uint256[]", "string"], + [ + "updateUintParameters", + 2, + 50, + 50, + [2], + 86400, + "QmZQhJunZesYuCJkdGwejSATTR8eynUgV8372cHvnAPMaM", + nullAddress, + toHex("MC"), + [0, 0], + "updateUintParameters(bytes8,uint256)", + ] + ); + 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()); + await increaseTime(604800); + }); + + it("Should update uint paramters", async function() { + let categoryId = await pc.totalCategories(); + categoryId = 19; + await updateParameter(categoryId, 2, "MAXRPSP", marketIncentives, "uint", 6000); + await updateParameter(categoryId, 2, "MINRPSP", marketIncentives, "uint", 7000); + await updateParameter(categoryId, 2, "PSFRPS", marketIncentives, "uint", 8000); + await updateParameter(categoryId, 2, "RPSTH", marketIncentives, "uint", 9000); + await updateInvalidParameter(categoryId, 2, "ABCD", marketIncentives, "uint", 10000); + }); + + it("Add category to update uint paramters of allMarkets", async function() { + let actionHash = encode1( + ["string", "uint256", "uint256", "uint256", "uint256[]", "uint256", "string", "address", "bytes2", "uint256[]", "string"], + [ + "updateUintParameters", + 2, + 50, + 50, + [2], + 86400, + "QmZQhJunZesYuCJkdGwejSATTR8eynUgV8372cHvnAPMaM", + nullAddress, + toHex("AM"), + [0, 0], + "updateUintParameters(bytes8,uint256)", + ] + ); + 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()); + await increaseTime(604800); + }); + + // it("Should update uint paramters", async function() { + // let categoryId = await pc.totalCategories(); + // categoryId = categoryId*1 - 1; + // await updateParameter(categoryId, 2, "ETHC", allMarkets, "uint", 5000); + // await updateParameter(categoryId, 2, "TKNC", allMarkets, "uint", 6000); + // await updateParameter(categoryId, 2, "ABCD", allMarkets, "uint", 10000); + // }) + + it("Add category to update address paramters of allMarkets", async function() { + let actionHash = encode1( + ["string", "uint256", "uint256", "uint256", "uint256[]", "uint256", "string", "address", "bytes2", "uint256[]", "string"], + [ + "updateAddressParameters", + 2, + 50, + 50, + [2], + 86400, + "QmZQhJunZesYuCJkdGwejSATTR8eynUgV8372cHvnAPMaM", + nullAddress, + toHex("MC"), + [0, 0], + "updateAddressParameters(bytes8,address)", + ] + ); + 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()); + await increaseTime(604800); + }); + + + it("Should add new market curreny with null address is passed as feed", async function() { + await increaseTime(604810); + pId = (await gv.getProposalLength()).toNumber(); + await gv.createProposal("Proposal2", "Proposal2", "Proposal2", 0); //Pid 3 + await gv.categorizeProposal(pId, 15, 0); + let startTime = (await latestTime()) / 1 + 2 * 604800; + let actionHash = encode("addMarketCurrency(bytes32,address,uint8,uint8,uint32)", toHex("LINK/PLOT"), nullAddress, 8, 1, startTime); + await gv.submitProposalWithSolution(pId, "addNewMarketCurrency", actionHash); + await gv.submitVote(pId, 1, { from: ab1 }); + await increaseTime(604810); + await assertRevert(gv.submitVote(pId, 1, { from: mem2 })); //closed to vote + await gv.closeProposal(pId); + let actionStatus = await gv.proposalActionStatus(pId); + assert.equal(actionStatus / 1, 3); + }); + + // it("Should update address paramters", async function() { + // let categoryId = await pc.totalCategories(); + // categoryId = categoryId*1 - 1; + // await updateParameter(categoryId, 2, "GASAGG", marketIncentives, "address", allMarkets.address); + // await updateInvalidParameter(categoryId, 2, "ABECD", marketIncentives, "address", allMarkets.address); + // }) + async function updateParameter(cId, mrSequence, code, contractInst, type, proposedValue) { + code = toHex(code); + let getterFunction; + if (type == "uint") { + action = "updateUintParameters(bytes8,uint256)"; + getterFunction = "getUintParameters"; + } else if (type == "address") { + action = "updateAddressParameters(bytes8,address)"; + getterFunction = "getAddressParameters"; + } + + let actionHash = encode(action, code, proposedValue); + let proposalId = await governance.getProposalLength(); + await gvProposal(cId, actionHash, mr, governance, mrSequence, 0); + if (code == toHex("MASTADD")) { + let newMaster = await NXMaster.at(proposedValue); + contractInst = newMaster; + } + let parameter; + if(code == toHex("ETHC")) { + let actionStatus = await governance.proposalActionStatus(proposalId*1); + assert.equal(actionStatus*1, 3, "Not updated"); + } else if(code == toHex("TKNC")) { + let actionStatus = await governance.proposalActionStatus(proposalId*1); + assert.equal(actionStatus*1, 3, "Not updated"); + } else if(code == toHex("ABCD")) { + let actionStatus = await governance.proposalActionStatus(proposalId*1); + assert.equal(actionStatus*1, 3); + } else { + // 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"); + // } + } + } + + async function updateInvalidParameter( + cId, + mrSequence, + code, + contractInst, + type, + proposedValue + ) { + code = toHex(code); + let getterFunction; + if (type == 'uint') { + action = 'updateUintParameters(bytes8,uint)'; + getterFunction = 'getUintParameters'; + } else { + action = "updateAddressParameters(bytes8,address)"; + getterFunction = "getAddressParameters"; + } + let actionHash = encode(action, code, proposedValue); + await gvProposal(cId, actionHash, mr, governance, mrSequence, 0); + if (code == toHex('MASTADD') && proposedValue != ZERO_ADDRESS) { + let newMaster = await NXMaster.at(proposedValue); + contractInst = newMaster; + } + let parameter = await contractInst[getterFunction](code); + try { + parameter[1] = parameter[1].toNumber(); + } catch (err) {} + assert.notEqual(parameter[1], proposedValue); + } +}); diff --git a/test/15_plotx.test.js b/test/15_plotx.test.js deleted file mode 100644 index 8d91db90d..000000000 --- a/test/15_plotx.test.js +++ /dev/null @@ -1,425 +0,0 @@ -const OwnedUpgradeabilityProxy = artifacts.require("OwnedUpgradeabilityProxy"); -const Governance = artifacts.require("Governance"); -const MemberRoles = artifacts.require("MemberRoles"); -const ProposalCategory = artifacts.require("ProposalCategory"); -const TokenController = artifacts.require("TokenController"); -const NXMaster = artifacts.require("Master"); -const Market = artifacts.require("MockMarket"); -const MarketConfig = artifacts.require("MockConfig"); -const MockUniswapRouter = artifacts.require("MockUniswapRouter"); -const PlotusToken = artifacts.require("MockPLOT"); -const Plotus = artifacts.require("MockMarketRegistry"); -const MockchainLink = artifacts.require("MockChainLinkAggregator"); -const assertRevert = require("./utils/assertRevert.js").assertRevert; -const increaseTime = require("./utils/increaseTime.js").increaseTime; -const latestTime = require("./utils/latestTime.js").latestTime; -const encode = require("./utils/encoder.js").encode; -const { toHex, toWei } = require("./utils/ethTools.js"); -const expectEvent = require("./utils/expectEvent"); -const gvProp = require("./utils/gvProposal.js").gvProposal; -const Web3 = require("web3"); -const { assert } = require("chai"); -// const gvProposalWithIncentive = require("./utils/gvProposal.js").gvProposalWithIncentive; -const gvProposal = require("./utils/gvProposal.js").gvProposalWithIncentiveViaTokenHolder; -const web3 = new Web3(); -const AdvisoryBoard = "0x41420000"; -let maxAllowance = "115792089237316195423570985008687907853269984665640564039457584007913129639935"; - -let gv; -let cr; -let pc; -let nxms; -let proposalId; -let pId; -let mr; -let plotusToken; -let tc; -let td; -let pl; -let mockchainLinkInstance; - -contract("PlotX", ([ab1, ab2, ab3, ab4, mem1, mem2, mem3, mem4, mem5, mem6, mem7, mem8, mem9, mem10, notMember, dr1, dr2, dr3]) => { - before(async function() { - nxms = await OwnedUpgradeabilityProxy.deployed(); - nxms = await NXMaster.at(nxms.address); - plotusToken = await PlotusToken.deployed(); - let address = await nxms.getLatestAddress(toHex("GV")); - gv = await Governance.at(address); - address = await nxms.getLatestAddress(toHex("PC")); - pc = await ProposalCategory.at(address); - address = await nxms.getLatestAddress(toHex("MR")); - mr = await MemberRoles.at(address); - address = await nxms.getLatestAddress(toHex("PL")); - pl = await Plotus.at(address); - mockchainLinkInstance = await MockchainLink.deployed(); - marketConfig = await pl.marketUtility(); - marketConfig = await MarketConfig.at(marketConfig); - MockUniswapRouterInstance = await MockUniswapRouter.deployed(); - tc = await TokenController.at(await nxms.getLatestAddress(toHex("TC"))); - await assertRevert(pl.setMasterAddress()); - // try { - // await (gv.setMasterAddress()); - // } catch (e) { - // console.log(e); - // } - await assertRevert(pl.callMarketResultEvent([1, 2], 1, 1,1)); - await assertRevert(pl.addInitialMarketTypesAndStart(Math.round(Date.now() / 1000), mem1, plotusToken.address, {from:mem2})); - await assertRevert(pl.addInitialMarketTypesAndStart(Math.round(Date.now() / 1000), mem1, plotusToken.address)); - await assertRevert(pl.initiate(mem1, mem1, mem1, [mem1, mem1, mem1, mem1])); - await plotusToken.transfer(mem1, toWei(100)); - await plotusToken.transfer(mem2, toWei(100)); - await plotusToken.transfer(mem3, toWei(100)); - await plotusToken.transfer(mem4, toWei(100)); - await plotusToken.transfer(mem5, toWei(100)); - - }); - - it("Should create a proposal to whitelist sponsor", async function() { - await increaseTime(604810); - pId = (await gv.getProposalLength()).toNumber(); - await gv.createProposal("Proposal2", "Proposal2", "Proposal2", 0); //Pid 3 - await gv.categorizeProposal(pId, 23, 0); - let startTime = (await latestTime()) / 1 + 2 * 604800; - let market= await Market.new(); - let actionHash = encode("whitelistSponsor(address)", ab1); - await gv.submitProposalWithSolution(pId, "whitelistSponsor", actionHash); - await gv.submitVote(pId, 1, { from: ab1 }); - await gv.submitVote(pId, 1, { from: mem1 }); - await gv.submitVote(pId, 1, { from: mem2 }); - await gv.submitVote(pId, 1, { from: mem3 }); - await gv.submitVote(pId, 1, { from: mem4 }); - await gv.submitVote(pId, 1, { from: mem5 }); - let canClose = await gv.canCloseProposal(pId); - assert.equal(canClose.toNumber(), 0); - await increaseTime(604810); - await assertRevert(gv.submitVote(pId, 1, { from: mem2 })); //closed to vote - await gv.closeProposal(pId); - let openMarketsBefore = await pl.getOpenMarkets(); - await increaseTime(604850); - await gv.triggerAction(pId); - let actionStatus = await gv.proposalActionStatus(pId); - assert.equal(actionStatus / 1, 3); - }); - - it("Should create a proposal to add new market curreny", async function() { - await increaseTime(604810); - pId = (await gv.getProposalLength()).toNumber(); - await gv.createProposal("Proposal2", "Proposal2", "Proposal2", 0); //Pid 3 - await gv.categorizeProposal(pId, 16, 0); - let startTime = (await latestTime()) / 1 + 2 * 604800; - let market= await Market.new(); - let actionHash = encode("addNewMarketCurrency(address,uint64)", market.address, startTime); - await gv.submitProposalWithSolution(pId, "addNewMarketCurrency", actionHash); - await gv.submitVote(pId, 1, { from: ab1 }); - await gv.submitVote(pId, 1, { from: mem1 }); - await gv.submitVote(pId, 1, { from: mem2 }); - await gv.submitVote(pId, 1, { from: mem3 }); - await gv.submitVote(pId, 1, { from: mem4 }); - await gv.submitVote(pId, 1, { from: mem5 }); - await increaseTime(604810); - await assertRevert(gv.submitVote(pId, 1, { from: mem2 })); //closed to vote - await gv.closeProposal(pId); - let openMarketsBefore = await pl.getOpenMarkets(); - await increaseTime(604850); - await gv.triggerAction(pId); - let actionStatus = await gv.proposalActionStatus(pId); - assert.equal(actionStatus / 1, 3); - let openMarkets = await pl.getOpenMarkets(); - assert.isAbove(openMarkets[2].length, openMarketsBefore[2].length, "Currency not added"); - }); - - it("Prredict on newly created market", async function() { - let openMarkets = await pl.getOpenMarkets(); - marketInstance = await Market.at(openMarkets[0][2]); - // await increaseTime(10001); - assert.ok(marketInstance); - await marketConfig.setOptionPrice(1, 9); - await marketConfig.setOptionPrice(2, 18); - await marketConfig.setOptionPrice(3, 27); - - // await marketConfig.setAMLComplianceStatus(ab1, true); - // await marketConfig.setKYCComplianceStatus(ab1, true); - - // set price - // user 1 - // set price lot - await MockUniswapRouterInstance.setPrice("1000000000000000"); - await marketConfig.setPrice("1000000000000000"); - await plotusToken.approve(tc.address, "18000000000000000000000000"); - await marketInstance.claimReturn(ab1); - await assertRevert(marketInstance.placePrediction(plotusToken.address, "10000000000000000000", 9, 1)); - await assertRevert(marketInstance.placePrediction(ab1, "10000000000000000000", 9, 1)); - await plotusToken.approve(tc.address, "18000000000000000000000000", {from:mem1}); - await plotusToken.approve(tc.address, "18000000000000000000000000"); - await assertRevert(marketInstance.sponsorIncentives(plotusToken.address, "1000000000000000000", {from:mem1})); - await marketInstance.sponsorIncentives(plotusToken.address, "1000000000000000000"); - await assertRevert(marketInstance.sponsorIncentives(plotusToken.address, "1000000000000000000")); - await marketInstance.placePrediction(plotusToken.address, "1000000000000000000000", 1, 1); - let totalStaked = await pl.getTotalAssetStakedByUser(ab1); - assert.equal(totalStaked[0]/1, "1000000000000000000000"); - await marketInstance.placePrediction(plotusToken.address, "8000000000000000000000", 1, 1); - await assertRevert(marketInstance.placePrediction("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", "10000000000000000000", 1, 1, { value: 1000 })); - await assertRevert(marketInstance.calculatePredictionResult(1)); - await assertRevert(marketInstance.calculatePredictionResult(0)); - await increaseTime(604810); - await marketInstance.claimReturn(ab1); - await marketInstance.calculatePredictionResult(1); - await assertRevert(marketInstance.sponsorIncentives(plotusToken.address, "1000000000000000000")); - await assertRevert(marketInstance.placePrediction(plotusToken.address, "10000000000000000000", 1, 1)); - await assertRevert(marketInstance.calculatePredictionResult(0)); - await marketInstance.claimReturn(ab1); - await increaseTime(604800); - }); - - it("Should create a proposal to add new market type", async function() { - await increaseTime(604810); - pId = (await gv.getProposalLength()).toNumber(); - await gv.createProposal("Proposal2", "Proposal2", "Proposal2", 0); //Pid 3 - await gv.categorizeProposal(pId, 15, 0); - let startTime = Math.round(Date.now()); - startTime = (await latestTime()) / 1 + 3 * 604800; - // startTime = Math.round((Date.now())/1000) + 2*604800; - let actionHash = encode("addNewMarketType(uint64,uint64,uint64)", 60 * 60 * 2, startTime, 10); - await gv.submitProposalWithSolution(pId, "update max followers limit", actionHash); - - actionHash = encode("addNewMarketType(uint64,uint64,uint64)", 60 * 60 * 2, 1, 10); - await assertRevert(gv.submitProposalWithSolution(pId, "update max followers limit", actionHash)); //should revert as start time is not enough - actionHash = encode("addNewMarketType(uint64,uint64,uint64)", 60 * 60 * 2, await latestTime(),10); - await assertRevert(gv.submitProposalWithSolution(pId, "update max followers limit", actionHash)); //should revert as start time is not enough - - await gv.submitVote(pId, 1, { from: ab1 }); - await gv.submitVote(pId, 1, { from: mem1 }); - await gv.submitVote(pId, 1, { from: mem2 }); - await gv.submitVote(pId, 1, { from: mem3 }); - await gv.submitVote(pId, 1, { from: mem4 }); - await gv.submitVote(pId, 1, { from: mem5 }); - await assertRevert(gv.triggerAction(pId)); //cannot trigger - await increaseTime(604810); - await assertRevert(gv.triggerAction(pId)); //cannot trigger - await gv.closeProposal(pId); - let openMarketsBefore = await pl.getOpenMarkets(); - await increaseTime(604810); - await gv.triggerAction(pId); - await assertRevert(gv.triggerAction(pId)); //cannot trigger - let actionStatus = await gv.proposalActionStatus(pId); - assert.equal(actionStatus / 1, 3); - let solutionAction = await gv.getSolutionAction(pId, 1); - assert.equal(parseFloat(solutionAction[0]), 1); - let voteData = await gv.voteTallyData(pId, 1); - assert.equal(parseFloat(voteData[0]), 1.50005e+25); - assert.equal(parseFloat(voteData[1]), 1); - assert.equal(parseFloat(voteData[2]), 6); - - let openMarkets = await pl.getOpenMarkets(); - assert.isAbove(openMarkets[1].length, openMarketsBefore[1].length, "Currency not added"); - }); - - it("Predict on newly created market", async function() { - let openMarkets = await pl.getOpenMarkets(); - await increaseTime(604810); - marketInstance = await Market.at(openMarkets[0][9]); - // await increaseTime(10001); - - assert.ok(marketInstance); - await marketConfig.setOptionPrice(1, 9); - await marketConfig.setOptionPrice(2, 18); - await marketConfig.setOptionPrice(3, 27); - await assertRevert(pl.createMarket(3, 0)); //should revert as market is live - - // await marketConfig.setAMLComplianceStatus(ab1, true); - // await marketConfig.setKYCComplianceStatus(ab1, true); - // set price - // user 1 - // set price lot - await MockUniswapRouterInstance.setPrice("1000000000000000"); - await marketConfig.setPrice("1000000000000000"); - await plotusToken.approve(tc.address, "100000000000000000000"); - await marketInstance.estimatePredictionValue(1, "10000000000000000000", 1); - await marketInstance.placePrediction(plotusToken.address, "10000000000000000000", 1, 1); - let reward = await marketInstance.getReturn(ab1); - assert.equal(reward[0].length, 0); - await increaseTime(3650); - await pl.createMarket(0, 0); - await increaseTime(604810); - await marketInstance.settleMarket(); - await increaseTime(604800); - // await pl.exchangeCommission(marketInstance.address); - await marketInstance.getData(); - // balanceBefore = (await plotusToken.balanceOf(ab1))/1; - // await marketInstance.claimReturn(ab1); - // balanceAfter = (await plotusToken.balanceOf(ab1))/1; - // assert.isAbove(balanceAfter, balanceBefore); - }); - - it("Claim Rewards", async function() { - await pl.getMarketDetailsUser(ab1, 0, 5); - await pl.getMarketDetailsUser(ab1, 5, 5); - await pl.getMarketDetailsUser(ab1, 0, 0); - let userDetails = await pl.getMarketDetailsUser(ab1, 0, 2); - assert.equal(userDetails[0].length, 2); - balanceBefore = (await plotusToken.balanceOf(ab1)) / 1; - await pl.claimPendingReturn(10); - await pl.claimPendingReturn(10); - balanceAfter = (await plotusToken.balanceOf(ab1)) / 1; - assert.isAbove(balanceAfter, balanceBefore); - await marketInstance.claimReturn(ab1); - }); - - it("Create market ", async function() { - // function createMarketFallback(_marketType, uint64 _marketCurrencyIndex) external payable{ - await pl.createMarket(0, 1); - await assertRevert(pl.createMarket(0, 1)); - await assertRevert(pl.createMarket(0, 1)); - - pId = (await gv.getProposalLength()).toNumber(); - await gvProposal(17, "0x", await MemberRoles.at(await nxms.getLatestAddress(toHex("MR"))), gv, 2, 0); - let actionStatus = await gv.proposalActionStatus(pId); - assert.equal(actionStatus / 1, 3); - await assertRevert(pl.createMarket(0, 1)); - }); -}); -contract("PlotX", ([ab1, ab2, ab3, ab4, mem1, mem2, mem3, mem4, mem5, mem6, mem7, mem8, mem9, mem10, notMember, dr1, dr2, dr3]) => { - before(async function() { - nxms = await OwnedUpgradeabilityProxy.deployed(); - nxms = await NXMaster.at(nxms.address); - plotusToken = await PlotusToken.deployed(); - let address = await nxms.getLatestAddress(toHex("GV")); - gv = await Governance.at(address); - address = await nxms.getLatestAddress(toHex("PC")); - pc = await ProposalCategory.at(address); - address = await nxms.getLatestAddress(toHex("MR")); - mr = await MemberRoles.at(address); - address = await nxms.getLatestAddress(toHex("PL")); - pl = await Plotus.at(address); - mockchainLinkInstance = await MockchainLink.deployed(); - marketConfig = await pl.marketUtility(); - marketConfig = await MarketConfig.at(marketConfig); - MockUniswapRouterInstance = await MockUniswapRouter.deployed(); - tc = await TokenController.at(await nxms.getLatestAddress(toHex("TC"))); - await assertRevert(pl.setMasterAddress()); - await assertRevert(pl.callMarketResultEvent([1, 2], 1, 1,1)); - - await plotusToken.transfer(mem1, toWei(100)); - await plotusToken.transfer(mem2, toWei(100)); - await plotusToken.transfer(mem3, toWei(100)); - await plotusToken.transfer(mem4, toWei(100)); - await plotusToken.transfer(mem5, toWei(100)); - - }); - - describe("Add new market currency",async function() { - - it("Should create a proposal to add new market curreny", async function() { - await increaseTime(604810); - pId = (await gv.getProposalLength()).toNumber(); - await gv.createProposal("Proposal2", "Proposal2", "Proposal2", 0); //Pid 3 - await gv.categorizeProposal(pId, 16, 100); - let startTime = (await latestTime()) / 1 + 2 * 604800; - let market= await Market.new(); - let actionHash = encode("addNewMarketCurrency(address,uint64)", market.address, startTime); - await gv.submitProposalWithSolution(pId, "addNewMarketCurrency", actionHash); - - await gv.submitVote(pId, 1, { from: ab1 }); - await gv.submitVote(pId, 1, { from: mem1 }); - await gv.submitVote(pId, 1, { from: mem2 }); - await gv.submitVote(pId, 1, { from: mem3 }); - await gv.submitVote(pId, 1, { from: mem4 }); - await gv.submitVote(pId, 1, { from: mem5 }); - - await increaseTime(604810); - await assertRevert(gv.submitVote(pId, 1, { from: mem2 })); //closed to vote - await gv.closeProposal(pId); - - let openMarketsBefore = await pl.getOpenMarkets(); - await increaseTime(604810); - await gv.triggerAction(pId); - let actionStatus = await gv.proposalActionStatus(pId); - assert.equal(actionStatus / 1, 3); - let openMarkets = await pl.getOpenMarkets(); - assert.isAbove(openMarkets[2].length, openMarketsBefore[2].length, "Currency not added"); - }); - - it("2. Should create a proposal to add new market currency", async function() { - await increaseTime(604810); - pId = (await gv.getProposalLength()).toNumber(); - await gv.createProposal("Proposal2", "Proposal2", "Proposal2", 0); //Pid 3 - await gv.categorizeProposal(pId, 16, 0); - let startTime = (await latestTime()) / 1 + 2 * 604800; - let market= await Market.new(); - let actionHash = encode("addNewMarketCurrency(address,uint64)", market.address, "0x12", "A", true, startTime); - await gv.submitProposalWithSolution(pId, "addNewMarketCurrency", actionHash); - oldGVBalance = parseFloat(await plotusToken.balanceOf(gv.address)); - await increaseTime(604810); - await gv.closeProposal(pId); - newGVBalance = parseFloat(await plotusToken.balanceOf(gv.address)); - assert.equal(oldGVBalance, newGVBalance); - await increaseTime(604810); - actionStatus = await gv.proposal(pId); - assert.equal(parseFloat(actionStatus[2]), 5); - }); - - it("Should revert claim market creation rewards if there is no balance at Registry", async function() { - let plBalance = await plotusToken.balanceOf(pl.address); - await pl.transferPlot(ab1, plBalance); - await assertRevert(pl.claimCreationReward()); - await plotusToken.transfer(pl.address, plBalance) - }); - - it("Should claim market creation rewards", async function() { - let oldBalance = parseFloat(await plotusToken.balanceOf(ab1)); - await pl.claimCreationReward(); - let newBalance = parseFloat(await plotusToken.balanceOf(ab1)); - assert.isAbove(newBalance/1,oldBalance/1); - await pl.getUintParameters("0x12"); - }); - - it("Should revert if unauthorized member call Registry functions", async function() { - await assertRevert(pl.claimCreationReward()); - await assertRevert(pl.createGovernanceProposal("","","","0x12",0,ab1, 0,0,0)); - await assertRevert(pl.setUserGlobalPredictionData(ab1, 0,0,ab1,0,0)); - await assertRevert(pl.callClaimedEvent(ab1, [0,0],[ab1],0,ab1)); - }); - - }); - - describe("Check Reward claim for multiple markets", async function() { - it("Should place prediction in multiple markets", async function() { - await increaseTime(604810); - await pl.createMarket(0, 0); - await pl.createMarket(2, 0); - let openMarkets = await pl.getOpenMarkets(); - marketInstance = await Market.at(openMarkets[0][0]); - marketInstance2 = await Market.at(openMarkets[0][6]); - - assert.ok(marketInstance); - await marketConfig.setOptionPrice(1, 9); - await marketConfig.setOptionPrice(2, 18); - await marketConfig.setOptionPrice(3, 27); - await MockUniswapRouterInstance.setPrice("1000000000000000"); - await marketConfig.setPrice("1000000000000000"); - await plotusToken.approve(tc.address, "180000000000000000000000000"); - await marketInstance.placePrediction(plotusToken.address, "10000000000000000000", 1, 1); - await marketInstance2.placePrediction(plotusToken.address, "10000000000000000000", 1, 1); - await increaseTime(3650); - await pl.createMarket(0, 0); - openMarkets = await pl.getOpenMarkets(); - marketInstance = await Market.at(openMarkets[0][0]); - await marketInstance.placePrediction(plotusToken.address, "10000000000000000000", 1, 1); - await increaseTime(604810); - await pl.createMarket(2, 1); - openMarkets = await pl.getOpenMarkets(); - marketInstance2 = await Market.at(openMarkets[0][7]); - await marketInstance2.placePrediction(plotusToken.address, "10000000000000000000", 1, 1); - await pl.createMarket(0, 0); - openMarkets = await pl.getOpenMarkets(); - marketInstance = await Market.at(openMarkets[0][0]); - await marketInstance.placePrediction(plotusToken.address, "10000000000000000000", 1, 1); - await increaseTime(604800); - }); - - it("Claim Rewards", async function() { - await pl.claimPendingReturn(20); - }); - }); - -}); diff --git a/test/18_TokenController.test.js b/test/18_TokenController.test.js index 0dafce595..fafc9e4db 100644 --- a/test/18_TokenController.test.js +++ b/test/18_TokenController.test.js @@ -2,7 +2,6 @@ const Master = artifacts.require("Master"); const TokenController = artifacts.require("MockTokenController"); const PlotusToken = artifacts.require("MockPLOT.sol"); const OwnedUpgradeabilityProxy = artifacts.require('OwnedUpgradeabilityProxy'); -const MockUniswapRouter = artifacts.require('MockUniswapRouter'); // const BLOT = artifacts.require("bLOTToken"); const Web3 = require("web3"); @@ -11,7 +10,7 @@ const { expectRevert, time } = require("@openzeppelin/test-helpers"); const { assert } = require("chai"); contract("TokenController", ([owner, account2, account3]) => { - let plotusToken, tokenController, uniswapRouter; + let plotusToken, tokenController; const lockReason1 = web3.utils.fromAscii("DR"); const lockReason2 = web3.utils.fromAscii("SM"); @@ -83,11 +82,9 @@ contract("TokenController", ([owner, account2, account3]) => { describe("Lock Functionality", () => { before(async () => { await plotusToken.burn( await plotusToken.balanceOf(owner), { from: owner }); - uniswapRouter = await MockUniswapRouter.deployed(); - await plotusToken.burnTokens(uniswapRouter.address, await plotusToken.balanceOf(uniswapRouter.address), { from: owner }); await plotusToken.mint(owner, 2000, { from: owner }); assert.equal((await plotusToken.balanceOf(owner)).toNumber(), 2000); - assert.equal(parseInt(web3.utils.fromWei(await tokenController.totalSupply())), 1e4); + assert.equal(parseInt(web3.utils.fromWei(await tokenController.totalSupply())), parseInt(web3.utils.fromWei(await plotusToken.totalSupply()))); await assertRevert(plotusToken.changeOperator(nullAddress)); await plotusToken.changeOperator(tokenController.address); assert.equal(await plotusToken.operator(), tokenController.address); diff --git a/test/19_UpdateConfigParams.test.js b/test/19_UpdateConfigParams.test.js index 701a5ac14..4259152d3 100644 --- a/test/19_UpdateConfigParams.test.js +++ b/test/19_UpdateConfigParams.test.js @@ -3,10 +3,9 @@ const ProposalCategory = artifacts.require('ProposalCategory'); const MemberRoles = artifacts.require('MemberRoles'); const Master = artifacts.require('Master'); const TokenController = artifacts.require('TokenController'); -const Plotus = artifacts.require("MarketRegistry"); const MarketConfig = artifacts.require('MarketUtility'); +const AllMarkets = artifacts.require('AllMarkets'); const PlotusToken = artifacts.require("MockPLOT"); -const MockUniswapFactory = artifacts.require('MockUniswapFactory'); const MockchainLink = artifacts.require('MockChainLinkAggregator'); const OwnedUpgradeabilityProxy = artifacts.require('OwnedUpgradeabilityProxy'); const gvProposal = require('./utils/gvProposal.js').gvProposalWithIncentiveViaTokenHolder; @@ -46,8 +45,8 @@ contract('Configure Global Parameters', accounts => { address = await ms.getLatestAddress('0x4d52'); mr = await MemberRoles.at(address); tc = await TokenController.at(await ms.getLatestAddress('0x5443')); - pl = await Plotus.at(await ms.getLatestAddress(toHex('PL'))); - marketConfig = await MarketConfig.at(await pl.marketUtility()); + allMarkets = await AllMarkets.at(await ms.getLatestAddress(toHex('AM'))); + marketConfig = await MarketConfig.at(await ms.getLatestAddress(toHex('MU'))); plotTok = await PlotusToken.deployed(); feedInstance = await MockchainLink.deployed() @@ -122,140 +121,101 @@ contract('Configure Global Parameters', accounts => { describe('Update Market Config Params', function() { - it('Should update market creation incentive', async function() { - await updateParameter(20, 2, 'MCRINC', pl, 'configUint', 100); - let configData = await pl.getUintParameters(toHex('MCRINC')); - assert.equal(configData[1], 100, 'Not updated'); - }); - - it('Should update STAKE WEIGHTAGE', async function() { - await updateParameter(20, 2, 'SW', pl, 'configUint', 60); - let configData = await marketConfig.getPriceCalculationParams(feedInstance.address); - assert.equal(configData[0], 60, 'Not updated'); - }); - - it('Should not update STAKE WEIGHTAGE if passed value > 100', async function() { - await updateParameter(20, 2, 'SW', pl, 'configUint', 200); - let configData = await marketConfig.getPriceCalculationParams(feedInstance.address); - assert.notEqual(configData[0], 200, 'updated'); - }); - - it('Should update STAKE WEIGHTAGE MIN AMOUNT', async function() { - await updateParameter(20, 2, 'SWMA', pl, 'configUint', toWei(100)); - let configData = await marketConfig.getPriceCalculationParams(feedInstance.address); - assert.equal(configData[1], toWei(100), 'Not updated'); - }); - - it('Should update Min Time Elapsed Divisor', async function() { - await updateParameter(20, 2, 'MTED', pl, 'configUint', toWei(10)); - let configData = await marketConfig.getPriceCalculationParams(feedInstance.address); - assert.equal(configData[3], toWei(10), 'Not updated'); - }); - it('Should update Min PredictionAmount', async function() { - await updateParameter(20, 2, 'MINPRD', pl, 'configUint', toWei(120)); + await updateParameter(24, 2, 'MINPRD', marketConfig, 'configUint', 75); let configData = await marketConfig.getBasicMarketDetails(); - assert.equal(configData[0], toWei(120), 'Not updated'); + assert.equal(configData[0], 75, 'Not updated'); }); it('Should update Max PredictionAmount', async function() { - await updateParameter(20, 2, 'MAXPRD', pl, 'configUint', toWei(120)); + await updateParameter(24, 2, 'MAXPRD', marketConfig, 'configUint', 80); let configData = await marketConfig.getBasicMarketDetails(); - assert.equal(configData[3], toWei(120), 'Not updated'); + assert.equal(configData[2]/1, 80, 'Not updated'); }); it('Should update Position Decimals', async function() { - await updateParameter(20, 2, 'PDEC', pl, 'configUint', 19); + await updateParameter(24, 2, 'PDEC', marketConfig, 'configUint', 19); let configData = await marketConfig.getBasicMarketDetails(); - assert.equal(configData[2], 19, 'Not updated'); + assert.equal(configData[1]/1, 19, 'Not updated'); + }); + + it('Should update Token Stake For Dispute', async function() { + await updateParameter(24, 2, 'TSDISP', pl, 'configUint', 26); + let configData = await marketConfig.getDisputeResolutionParams(); + assert.equal(configData, 26, 'Not updated'); }); it('Should update Min Stake For Multiplier', async function() { - await updateParameter(20, 2, 'MINSTM', pl, 'configUint', 23); - let configData = await marketConfig.getValueAndMultiplierParameters(pl.address, 10); + await updateParameter(24, 2, 'SFMS', marketConfig, 'configUint', 23); + let configData = await marketConfig.getPriceCalculationParams(); assert.equal(configData[0], 23, 'Not updated'); }); - it('Should update Loss Percentage', async function() { - await updateParameter(20, 2, 'RPERC', pl, 'configUint', 24); - let configData = await marketConfig.getBasicMarketDetails(); + it('Should Staking Factor Weightage and Current Price weightage', async function() { + await updateParameter(24, 2, 'SFCPW', marketConfig, 'configUint', 24); + let configData = await marketConfig.getPriceCalculationParams(); assert.equal(configData[1], 24, 'Not updated'); - }); - - it('Should update Token Stake For Dispute', async function() { - await updateParameter(20, 2, 'TSDISP', pl, 'configUint', 26); - let configData = await marketConfig.getDisputeResolutionParams(); - assert.equal(configData, 26, 'Not updated'); + assert.equal(configData[2], 100-24, 'Not updated'); }); it('Should not update if invalid code is passed', async function() { - await updateParameter(20, 2, 'CDTIM1', pl, 'configUint', 28); + await updateParameter(24, 2, 'CDTIM1', pl, 'configUint', 28); }); it('Should not allow to update if unauthorized call', async function() { - await assertRevert(marketConfig.updateAddressParameters(toHex("UNIFAC"),pl.address)); + await assertRevert(marketConfig.updateUintParameters(toHex("UNIFAC"),100)); }); - it('Should update Uniswap Factory', async function() { - let uniswapFactory = await MockUniswapFactory.new(); - await updateParameter(21, 2, 'UNIFAC', pl, 'configAddress', uniswapFactory.address); - let configData = await marketConfig.getFeedAddresses(); - assert.equal(configData, uniswapFactory.address, 'Not updated'); - }); - - it('Should not update if invalid code is passed', async function() { - await updateParameter(21, 2, 'CDTIM1', pl, 'configAddress', pl.address); - }); }); describe('Update Token Controller Parameters', function() { it('Should update Lock period for Stake multiplier', async function() { - await updateParameter(14, 2, 'SMLP', tc, 'uint', '2'); + await updateParameter(13, 2, 'SMLP', tc, 'uint', '2'); }); it('Should not update if parameter code is incorrect', async function() { - await updateInvalidParameter(14, 2, 'EPTIM', tc, 'uint', '86400'); + await updateInvalidParameter(13, 2, 'EPTIM', tc, 'uint', '86400'); }); }); - describe('Update Governance Parameters', function() { + describe('Update MemberRoles Parameters', function() { it('Should update Min Token Locked For DR', async function() { - await updateParameter(22, 2, 'MNLOCKDR', mr, 'uint', '123'); + await updateParameter(20, 2, 'MNLOCKDR', mr, 'uint', '123'); }); it('Should update Lock Time For DR', async function() { - await updateParameter(22, 2, 'TLOCDR', mr, 'uint', '123'); + await updateParameter(20, 2, 'TLOCDR', mr, 'uint', '123'); }); it('Should not update if parameter code is incorrect', async function() { - await updateInvalidParameter(13, 2, 'EPTIM', mr, 'uint', '86400'); + await updateInvalidParameter(20, 2, 'EPTIM', mr, 'uint', '86400'); }); }); describe('Update Governance Parameters', function() { it('Should update Governance Token Holding Time', async function() { - await updateParameter(13, 2, 'GOVHOLD', gv, 'uint', '86400'); + await updateParameter(12, 2, 'GOVHOLD', gv, 'uint', '86400'); }); it('Should update AB majority', async function() { - await updateParameter(13, 2, 'ABMAJ', gv, 'uint', '20'); + await updateParameter(12, 2, 'ABMAJ', gv, 'uint', '20'); }); it('Should update Max Draft time limit', async function() { - await updateParameter(13, 2, 'MAXDRFT', gv, 'uint', '86400'); - }); - it('Should update Action Reject Auth Role', async function() { - await updateParameter(13, 2, 'REJAUTH', gv, 'uint', '123'); + await updateParameter(12, 2, 'MAXDRFT', gv, 'uint', '3600'); }); - it('Should update Action Reject Auth Role', async function() { - await updateParameter(13, 2, 'DRQUMR', gv, 'uint', '123'); + // it('Should update Action Reject Auth Role', async function() { + // await updateParameter(12, 2, 'REJAUTH', gv, 'uint', '12'); + // }); + it('Should update DR quorum multiplier', async function() { + await updateParameter(12, 2, 'DRQUMR', gv, 'uint', '35'); }); - it('Should update Vote Perc Reject Action', async function() { - await updateParameter(13, 2, 'REJCOUNT', gv, 'uint', '123'); + it('Should update members required to Reject action ', async function() { + await updateParameter(12, 2, 'REJCOUNT', gv, 'uint', '19'); }); it('Should update max vote weigthage percent', async function() { - await updateParameter(13, 2, 'MAXVW', gv, 'uint', '43'); + await updateParameter(12, 2, 'MAXVW', gv, 'uint', '27'); }); it('Should not update if parameter code is incorrect', async function() { - await updateInvalidParameter(13, 2, 'EPTIM', gv, 'uint', '86400'); + await updateInvalidParameter(12, 2, 'EPTIM', gv, 'uint', '86400'); }); it('Should update Action Waiting Time', async function() { - await updateParameter(13, 2, 'ACWT', gv, 'uint', '123'); + await updateParameter(12, 2, 'ACWT', gv, 'uint', '123'); }); }); diff --git a/test/21_weeklyMarketOptionPrice.js b/test/21_weeklyMarketOptionPrice.js index ef6b301da..680352c08 100644 --- a/test/21_weeklyMarketOptionPrice.js +++ b/test/21_weeklyMarketOptionPrice.js @@ -1,460 +1,242 @@ const { assert } = require("chai"); -const Market = artifacts.require("MockMarket"); -const Plotus = artifacts.require("MarketRegistry"); const OwnedUpgradeabilityProxy = artifacts.require("OwnedUpgradeabilityProxy"); const Master = artifacts.require("Master"); -const PlotusToken = artifacts.require("MockPLOT"); -const MarketConfig = artifacts.require("MockConfig"); const TokenController = artifacts.require("TokenController"); +const PlotusToken = artifacts.require("MockPLOT"); const MockchainLinkBTC = artifacts.require("MockChainLinkAggregator"); +const MarketConfig = artifacts.require("MockConfig"); const BLOT = artifacts.require("BLOT"); -const web3 = Market.web3; +const AllMarkets = artifacts.require("AllMarkets"); const increaseTime = require("./utils/increaseTime.js").increaseTime; +const increaseTimeTo = require("./utils/increaseTime.js").increaseTimeTo; +const { encode, encode1,encode3 } = require("./utils/encoder.js"); +const signAndExecuteMetaTx = require("./utils/signAndExecuteMetaTx.js").signAndExecuteMetaTx; +const { toHex, toWei, toChecksumAddress } = require("./utils/ethTools"); +let privateKeyList = ["fb437e3e01939d9d4fef43138249f23dc1d0852e69b0b5d1647c087f869fabbd","7c85a1f1da3120c941b83d71a154199ee763307683f206b98ad92c3b4e0af13e","ecc9b35bf13bd5459350da564646d05c5664a7476fe5acdf1305440f88ed784c","f4470c3fca4dbef1b2488d016fae25978effc586a1f83cb29ac8cb6ab5bc2d50","141319b1a84827e1046e93741bf8a9a15a916d49684ab04925ac4ce4573eea23","d54b606094287758dcf19064a8d91c727346aadaa9388732e73c4315b7c606f9","49030e42ce4152e715a7ddaa10e592f8e61d00f70ef11f48546711f159d985df","b96761b1e7ebd1e8464a78a98fe52f53ce6035c32b4b2b12307a629a551ff7cf","d4786e2581571c863c7d12231c3afb6d4cef390c0ac9a24b243293721d28ea95","ed28e3d3530544f1cf2b43d1956b7bd13b63c612d963a8fb37387aa1a5e11460","05b127365cf115d4978a7997ee98f9b48f0ddc552b981c18aa2ee1b3e6df42c6","9d11dd6843f298b01b34bd7f7e4b1037489871531d14b58199b7cba1ac0841e6","f79e90fa4091de4fc2ec70f5bf67b24393285c112658e0d810e6bd711387fbb9","99f1fc0f09230ce745b6a256ba7082e6e51a2907abda3d9e735a5c8188bb4ba1","477f86cce983b9c91a36fdcd4a7ce21144a08dee9b1aafb91b9c70e57f717ce6","b03d2e6bb4a7d71c66a66ff9e9c93549cae4b593f634a4ea2a1f79f94200f5b4","9ddc0f53a81e631dcf39d5155f41ec12ed551b731efc3224f410667ba07b37dc","cf087ff9ae7c9954ad8612d071e5cdf34a6024ee1ae477217639e63a802a53dd","b64f62b94babb82cc78d3d1308631ae221552bb595202fc1d267e1c29ce7ba60","a91e24875f8a534497459e5ccb872c4438be3130d8d74b7e1104c5f94cdcf8c2","4f49f3d029eeeb3fed14d59625acd088b6b34f3b41c527afa09d29e4a7725c32","179795fd7ac7e7efcba3c36d539a1e8659fb40d77d0a3fab2c25562d99793086","4ba37d0b40b879eceaaca2802a1635f2e6d86d5c31e3ff2d2fd13e68dd2a6d3d","6b7f5dfba9cd3108f1410b56f6a84188eee23ab48a3621b209a67eea64293394","870c540da9fafde331a3316cee50c17ad76ddb9160b78b317bef2e6f6fc4bac0","470b4cccaea895d8a5820aed088357e380d66b8e7510f0a1ea9b575850160241","8a55f8942af0aec1e0df3ab328b974a7888ffd60ded48cc6862013da0f41afbc","2e51e8409f28baf93e665df2a9d646a1bf9ac8703cbf9a6766cfdefa249d5780","99ef1a23e95910287d39493d8d9d7d1f0b498286f2b1fdbc0b01495f10cf0958","6652200c53a4551efe2a7541072d817562812003f9d9ef0ec17995aa232378f8","39c6c01194df72dda97da2072335c38231ced9b39afa280452afcca901e73643","12097e411d948f77b7b6fa4656c6573481c1b4e2864c1fca9d5b296096707c45","cbe53bf1976aee6cec830a848c6ac132def1503cffde82ccfe5bd15e75cbaa72","eeab5dcfff92dbabb7e285445aba47bd5135a4a3502df59ac546847aeb5a964f","5ea8279a578027abefab9c17cef186cccf000306685e5f2ee78bdf62cae568dd","0607767d89ad9c7686dbb01b37248290b2fa7364b2bf37d86afd51b88756fe66","e4fd5f45c08b52dae40f4cdff45e8681e76b5af5761356c4caed4ca750dc65cd","145b1c82caa2a6d703108444a5cf03e9cb8c3cd3f19299582a564276dbbba734","736b22ec91ae9b4b2b15e8d8c220f6c152d4f2228f6d46c16e6a9b98b4733120","ac776cb8b40f92cdd307b16b83e18eeb1fbaa5b5d6bd992b3fda0b4d6de8524c","65ba30e2202fdf6f37da0f7cfe31dfb5308c9209885aaf4cef4d572fd14e2903","54e8389455ec2252de063e83d3ce72529d674e6d2dc2070661f01d4f76b63475","fbbbfb525dd0255ee332d51f59648265aaa20c2e9eff007765cf4d4a6940a849","8de5e418f34d04f6ea947ce31852092a24a705862e6b810ca9f83c2d5f9cda4d","ea6040989964f012fd3a92a3170891f5f155430b8bbfa4976cde8d11513b62d9","14d94547b5deca767137fbd14dae73e888f3516c742fad18b83be333b38f0b88","47f05203f6368d56158cda2e79167777fc9dcb0c671ef3aabc205a1636c26a29"]; -contract("Market", async function([user1, user2, user3, user4, user5, user6, user7, user8, user9, user10]) { - it("1.Scenario 1 - Stake in ETH < minstake (no stake in LOT) and time passed < min time passed", async () => { - let tokenPrice = 0.01; - let masterInstance = await OwnedUpgradeabilityProxy.deployed(); - masterInstance = await Master.at(masterInstance.address); - let plotusToken = await PlotusToken.deployed(); - let BLOTInstance = await BLOT.deployed(); - let MockchainLinkInstance = await MockchainLinkBTC.deployed(); - let plotusNewAddress = await masterInstance.getLatestAddress(web3.utils.toHex("PL")); - tokenController =await TokenController.at(await masterInstance.getLatestAddress(web3.utils.toHex("TC"))); - let plotusNewInstance = await Plotus.at(plotusNewAddress); - let marketConfig = await plotusNewInstance.marketUtility(); - marketConfig = await MarketConfig.at(marketConfig); - const openMarkets = await plotusNewInstance.getOpenMarkets(); - //console.log("marketType", openMarkets["_marketTypes"][4] / 1); - marketInstance = await Market.at(openMarkets["_openMarkets"][4]); - await marketConfig.setMockPriceFlag(false); - await increaseTime(10001); - assert.ok(marketInstance); - - await MockchainLinkInstance.setLatestAnswer(1195000000000); - let currentPriceAfter = await MockchainLinkInstance.latestAnswer(); - //console.log(currentPriceAfter / 1); - - await marketInstance.setOptionRangesPublic(11900, 12000); - let priceOption1 = await marketInstance.getOptionPrice(1); - let priceOption2 = await marketInstance.getOptionPrice(2); - let priceOption3 = await marketInstance.getOptionPrice(3); - //console.log(priceOption1 / 1, priceOption2 / 1, priceOption3 / 1); +truncNumber = (n) => Math.trunc(n * Math.pow(10, 2)) / Math.pow(10, 2); +let masterInstance,plotusToken,BLOTInstance,MockchainLinkInstance,allMarkets; - +contract("Market", async function([user1, user2, user3, user4]) { - await marketInstance.placePrediction("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", "1000000000000000000", 1, 1, { - value: "1000000000000000000", - from: user1, - }); - - await marketInstance.placePrediction("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", "2000000000000000000", 2, 1, { - value: "2000000000000000000", - from: user2, - }); - - await marketInstance.placePrediction("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", "10000000000000000000", 3, 1, { - value: "10000000000000000000", - from: user3, - }); - - await increaseTime(21600); - let currentPriceAfter_af = await MockchainLinkInstance.latestAnswer(); - //console.log(currentPriceAfter_af / 1); - let priceOption1_af = await marketInstance.getOptionPrice(1); - let priceOption2_af = await marketInstance.getOptionPrice(2); - let priceOption3_af = await marketInstance.getOptionPrice(3); - let optionPriceETH1 = priceOption1_af / 1; - let optionPriceLOT1 = priceOption1_af / tokenPrice; - //console.log("Round off ETH price of option1", optionPriceETH1 / 1000); - //console.log("Round off LOT price of option1", optionPriceLOT1 / 1000); - let optionPriceETH2 = priceOption2_af / 1; - let optionPriceLOT2 = priceOption2_af / 1 / tokenPrice; - //console.log("Round off ETH price of option2", optionPriceETH2 / 1000); - //console.log("Round off LOT price of option2", optionPriceLOT2 / 1000); - let optionPriceETH3 = priceOption3_af / 1; - let optionPriceLOT3 = priceOption3_af / 1 / tokenPrice; - //console.log("Round off ETH price of option3", optionPriceETH3 / 1000); - //console.log("Round off LOT price of option3", optionPriceLOT3 / 1000); - }); -}); - -contract("Market", async function([user1, user2, user3, user4, user5, user6, user7, user8, user9, user10]) { - it("2.Scenario 2 - Stake in LOT< minstake (no stake in ETH) and time passed < min time passed", async () => { - let tokenPrice = 0.01; - let masterInstance = await OwnedUpgradeabilityProxy.deployed(); + before(async function () { + masterInstance = await OwnedUpgradeabilityProxy.deployed(); masterInstance = await Master.at(masterInstance.address); - let plotusToken = await PlotusToken.deployed(); - let BLOTInstance = await BLOT.deployed(); - let MockchainLinkInstance = await MockchainLinkBTC.deployed(); - let plotusNewAddress = await masterInstance.getLatestAddress(web3.utils.toHex("PL")); - let plotusNewInstance = await Plotus.at(plotusNewAddress); - let marketConfig = await plotusNewInstance.marketUtility(); - marketConfig = await MarketConfig.at(marketConfig); - const openMarkets = await plotusNewInstance.getOpenMarkets(); - //console.log("marketType", openMarkets["_marketTypes"][4] / 1); - marketInstance = await Market.at(openMarkets["_openMarkets"][4]); + plotusToken = await PlotusToken.deployed(); + BLOTInstance = await BLOT.deployed(); + MockchainLinkInstance = await MockchainLinkBTC.deployed(); + allMarkets = await AllMarkets.at(await masterInstance.getLatestAddress(web3.utils.toHex("AM"))); + marketConfig = await MarketConfig.at(await masterInstance.getLatestAddress(web3.utils.toHex("MU"))); + await marketConfig.setMockPriceFlag(false); - await increaseTime(10001); - assert.ok(marketInstance); + let expireT = await allMarkets.getMarketData(5); + + await increaseTimeTo(expireT[5]); await MockchainLinkInstance.setLatestAnswer(1195000000000); let currentPriceAfter = await MockchainLinkInstance.latestAnswer(); - //console.log(currentPriceAfter / 1); - await marketInstance.setOptionRangesPublic(11900, 12000); - let priceOption1 = await marketInstance.getOptionPrice(1); - let priceOption2 = await marketInstance.getOptionPrice(2); - let priceOption3 = await marketInstance.getOptionPrice(3); - //console.log(priceOption1 / 1, priceOption2 / 1, priceOption3 / 1); + }); + + it("1.Scenario 1 - Stake < minstakes and time passed < min time passed", async () => { + + await allMarkets.createMarket(0, 2); + await increaseTime(6*3600); + + let maxMin = await allMarkets.getMarketData(7); + + await plotusToken.transfer(user2, toWei(10000)); + await plotusToken.approve(allMarkets.address, toWei(100000), { from: user2 }); + let functionSignature = encode3("depositAndPlacePrediction(uint,uint,address,uint64,uint256)", toWei(10000), 7, plotusToken.address, 10000*1e8, 1); + await signAndExecuteMetaTx( + privateKeyList[1], + user2, + functionSignature, + allMarkets, + "AM" + ); + + await plotusToken.transfer(user3, toWei(2000)); + await plotusToken.approve(allMarkets.address, toWei(100000), { from: user3 }); + functionSignature = encode3("depositAndPlacePrediction(uint,uint,address,uint64,uint256)", toWei(2000), 7, plotusToken.address, 2000*1e8, 2); + await signAndExecuteMetaTx( + privateKeyList[2], + user3, + functionSignature, + allMarkets, + "AM" + ); + + await plotusToken.transfer(user4, toWei(5000)); + await plotusToken.approve(allMarkets.address, toWei(100000), { from: user4 }); + functionSignature = encode3("depositAndPlacePrediction(uint,uint,address,uint64,uint256)", toWei(5000), 7, plotusToken.address, 5000*1e8, 3); + await signAndExecuteMetaTx( + privateKeyList[3], + user4, + functionSignature, + allMarkets, + "AM" + ); + + + + assert.equal(await marketConfig.getOptionPrice(7,1), 25000); + assert.equal(await marketConfig.getOptionPrice(7,2), 50000); + assert.equal(await marketConfig.getOptionPrice(7,3), 25000); + }); + it("2.Scenario 2 - Stake > minstakes and time passed < min time passed", async () => { - await plotusToken.approve(tokenController.address, "10000000000000000000000"); - await marketInstance.placePrediction(plotusToken.address, "100000000000000000000", 1, 1, { - from: user1, - }); - - await marketInstance.placePrediction(plotusToken.address, "100000000000000000000", 2, 1, { - from: user1, - }); - - await marketInstance.placePrediction(plotusToken.address, "100000000000000000000", 3, 1, { - from: user1, - }); - - await increaseTime(21600); - let currentPriceAfter_af = await MockchainLinkInstance.latestAnswer(); - //console.log(currentPriceAfter_af / 1); - let priceOption1_af = await marketInstance.getOptionPrice(1); - let priceOption2_af = await marketInstance.getOptionPrice(2); - let priceOption3_af = await marketInstance.getOptionPrice(3); - let optionPriceETH1 = priceOption1_af / 1; - let optionPriceLOT1 = priceOption1_af / tokenPrice; - //console.log("Round off ETH price of option1", optionPriceETH1 / 1000); - //console.log("Round off LOT price of option1", optionPriceLOT1 / 1000); - let optionPriceETH2 = priceOption2_af / 1; - let optionPriceLOT2 = priceOption2_af / 1 / tokenPrice; - //console.log("Round off ETH price of option2", optionPriceETH2 / 1000); - //console.log("Round off LOT price of option2", optionPriceLOT2 / 1000); - let optionPriceETH3 = priceOption3_af / 1; - let optionPriceLOT3 = priceOption3_af / 1 / tokenPrice; - //console.log("Round off ETH price of option3", optionPriceETH3 / 1000); - //console.log("Round off LOT price of option3", optionPriceLOT3 / 1000); + let expireT = await allMarkets.getMarketData(7); + + await increaseTimeTo(expireT[5]); + + await allMarkets.createMarket(0, 2); + + + + await plotusToken.transfer(user2, toWei(10000)); + await plotusToken.approve(allMarkets.address, toWei(100000), { from: user2 }); + let functionSignature = encode3("depositAndPlacePrediction(uint,uint,address,uint64,uint256)", toWei(10000), 8, plotusToken.address, 10000*1e8, 1); + await signAndExecuteMetaTx( + privateKeyList[1], + user2, + functionSignature, + allMarkets, + "AM" + ); + + await plotusToken.transfer(user3, toWei(5000)); + await plotusToken.approve(allMarkets.address, toWei(100000), { from: user3 }); + functionSignature = encode3("depositAndPlacePrediction(uint,uint,address,uint64,uint256)", toWei(5000), 8, plotusToken.address, 5000*1e8, 2); + await signAndExecuteMetaTx( + privateKeyList[2], + user3, + functionSignature, + allMarkets, + "AM" + ); + + await plotusToken.transfer(user4, toWei(40000)); + await plotusToken.approve(allMarkets.address, toWei(100000), { from: user4 }); + functionSignature = encode3("depositAndPlacePrediction(uint,uint,address,uint64,uint256)", toWei(40000), 8, plotusToken.address, 40000*1e8, 3); + await signAndExecuteMetaTx( + privateKeyList[3], + user4, + functionSignature, + allMarkets, + "AM" + ); + + let optionPricePaams = await allMarkets.getMarketOptionPricingParams(8,1); + await increaseTimeTo(optionPricePaams[1]/1+6*3600); + + + assert.equal(truncNumber((await marketConfig.getOptionPrice(8,1))/1e5), 0.19); + assert.equal(truncNumber((await marketConfig.getOptionPrice(8,2))/1e5), 0.16); + assert.equal(truncNumber((await marketConfig.getOptionPrice(8,3))/1e5), 0.63); }); -}); -contract("Market", async function([user1, user2, user3, user4, user5, user6, user7, user8, user9, user10]) { - it("3.Scenario 3 - Stake in LOT+ETH> minstake and time passed < min time passed", async () => { - let tokenPrice = 0.01; - let masterInstance = await OwnedUpgradeabilityProxy.deployed(); - masterInstance = await Master.at(masterInstance.address); - let plotusToken = await PlotusToken.deployed(); - let BLOTInstance = await BLOT.deployed(); - let MockchainLinkInstance = await MockchainLinkBTC.deployed(); - let plotusNewAddress = await masterInstance.getLatestAddress(web3.utils.toHex("PL")); - let plotusNewInstance = await Plotus.at(plotusNewAddress); - let marketConfig = await plotusNewInstance.marketUtility(); - marketConfig = await MarketConfig.at(marketConfig); - const openMarkets = await plotusNewInstance.getOpenMarkets(); - //console.log("marketType", openMarkets["_marketTypes"][4] / 1); - marketInstance = await Market.at(openMarkets["_openMarkets"][4]); - await marketConfig.setMockPriceFlag(false); - await increaseTime(10001); - assert.ok(marketInstance); + it("3.Scenario 3 - Stake > minstakes and time passed > min time passed", async () => { - await MockchainLinkInstance.setLatestAnswer(1195000000000); - let currentPriceAfter = await MockchainLinkInstance.latestAnswer(); - //console.log(currentPriceAfter / 1); - await marketInstance.setOptionRangesPublic(11900, 12000); - let priceOption1 = await marketInstance.getOptionPrice(1); - let priceOption2 = await marketInstance.getOptionPrice(2); - let priceOption3 = await marketInstance.getOptionPrice(3); - //console.log(priceOption1 / 1, priceOption2 / 1, priceOption3 / 1); + let expireT = await allMarkets.getMarketData(8); - + await increaseTimeTo(expireT[5]); - await plotusToken.approve(tokenController.address, "10000000000000000000000"); - await marketInstance.placePrediction(plotusToken.address, "100000000000000000000", 1, 1, { - from: user1, - }); - - await marketInstance.placePrediction(plotusToken.address, "100000000000000000000", 2, 1, { - from: user1, - }); - - await marketInstance.placePrediction(plotusToken.address, "100000000000000000000", 3, 1, { - from: user1, - }); - - await marketInstance.placePrediction("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", "1000000000000000000", 1, 1, { - value: "1000000000000000000", - from: user1, - }); - - await marketInstance.placePrediction("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", "10000000000000000000", 2, 1, { - value: "10000000000000000000", - from: user2, - }); - - await marketInstance.placePrediction("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", "5000000000000000000", 3, 1, { - value: "5000000000000000000", - from: user2, - }); - - await increaseTime(21600); - let currentPriceAfter_af = await MockchainLinkInstance.latestAnswer(); - //console.log(currentPriceAfter_af / 1); - let priceOption1_af = await marketInstance.getOptionPrice(1); - let priceOption2_af = await marketInstance.getOptionPrice(2); - let priceOption3_af = await marketInstance.getOptionPrice(3); - let optionPriceETH1 = priceOption1_af / 1; - let optionPriceLOT1 = priceOption1_af / tokenPrice; - //console.log("Round off ETH price of option1", optionPriceETH1 / 1000); - //console.log("Round off LOT price of option1", optionPriceLOT1 / 1000); - let optionPriceETH2 = priceOption2_af / 1; - let optionPriceLOT2 = priceOption2_af / 1 / tokenPrice; - //console.log("Round off ETH price of option2", optionPriceETH2 / 1000); - //console.log("Round off LOT price of option2", optionPriceLOT2 / 1000); - let optionPriceETH3 = priceOption3_af / 1; - let optionPriceLOT3 = priceOption3_af / 1 / tokenPrice; - //console.log("Round off ETH price of option3", optionPriceETH3 / 1000); - //console.log("Round off LOT price of option3", optionPriceLOT3 / 1000); - }); -}); + await allMarkets.createMarket(0, 2); -contract("Market", async function([user1, user2, user3, user4, user5, user6, user7, user8, user9, user10]) { - it("4.Scenario 3 - Stake in LOT+ETH> minstake and time passed < min time passed", async () => { - let tokenPrice = 0.01; - let masterInstance = await OwnedUpgradeabilityProxy.deployed(); - masterInstance = await Master.at(masterInstance.address); - let plotusToken = await PlotusToken.deployed(); - let BLOTInstance = await BLOT.deployed(); - let MockchainLinkInstance = await MockchainLinkBTC.deployed(); - let plotusNewAddress = await masterInstance.getLatestAddress(web3.utils.toHex("PL")); - let plotusNewInstance = await Plotus.at(plotusNewAddress); - let marketConfig = await plotusNewInstance.marketUtility(); - marketConfig = await MarketConfig.at(marketConfig); - const openMarkets = await plotusNewInstance.getOpenMarkets(); - //console.log("marketType", openMarkets["_marketTypes"][4] / 1); - marketInstance = await Market.at(openMarkets["_openMarkets"][4]); - await marketConfig.setMockPriceFlag(false); - await increaseTime(10001); - assert.ok(marketInstance); - await MockchainLinkInstance.setLatestAnswer(1195000000000); - let currentPriceAfter = await MockchainLinkInstance.latestAnswer(); - //console.log(currentPriceAfter / 1); - await marketInstance.setOptionRangesPublic(11900, 12000); - let priceOption1 = await marketInstance.getOptionPrice(1); - let priceOption2 = await marketInstance.getOptionPrice(2); - let priceOption3 = await marketInstance.getOptionPrice(3); - //console.log(priceOption1 / 1, priceOption2 / 1, priceOption3 / 1); + await plotusToken.transfer(user2, toWei(10000)); + await plotusToken.approve(allMarkets.address, toWei(100000), { from: user2 }); + let functionSignature = encode3("depositAndPlacePrediction(uint,uint,address,uint64,uint256)", toWei(10000), 9, plotusToken.address, 10000*1e8, 1); + await signAndExecuteMetaTx( + privateKeyList[1], + user2, + functionSignature, + allMarkets, + "AM" + ); - + await plotusToken.transfer(user3, toWei(5000)); + await plotusToken.approve(allMarkets.address, toWei(100000), { from: user3 }); + functionSignature = encode3("depositAndPlacePrediction(uint,uint,address,uint64,uint256)", toWei(5000), 9, plotusToken.address, 5000*1e8, 2); + await signAndExecuteMetaTx( + privateKeyList[2], + user3, + functionSignature, + allMarkets, + "AM" + ); - await plotusToken.approve(tokenController.address, "10000000000000000000000"); - await marketInstance.placePrediction(plotusToken.address, "100000000000000000000", 1, 1, { - from: user1, - }); - - await marketInstance.placePrediction(plotusToken.address, "100000000000000000000", 2, 1, { - from: user1, - }); - - await marketInstance.placePrediction(plotusToken.address, "100000000000000000000", 3, 1, { - from: user1, - }); - - await marketInstance.placePrediction("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", "1000000000000000000", 1, 1, { - value: "1000000000000000000", - from: user1, - }); - - await marketInstance.placePrediction("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", "10000000000000000000", 2, 1, { - value: "10000000000000000000", - from: user2, - }); - - await marketInstance.placePrediction("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", "5000000000000000000", 3, 1, { - value: "5000000000000000000", - from: user2, - }); - - await increaseTime(21600); - let currentPriceAfter_af = await MockchainLinkInstance.latestAnswer(); - //console.log(currentPriceAfter_af / 1); - let priceOption1_af = await marketInstance.getOptionPrice(1); - let priceOption2_af = await marketInstance.getOptionPrice(2); - let priceOption3_af = await marketInstance.getOptionPrice(3); - let optionPriceETH1 = priceOption1_af / 1; - let optionPriceLOT1 = priceOption1_af / tokenPrice; - //console.log("Round off ETH price of option1", optionPriceETH1 / 1000); - //console.log("Round off LOT price of option1", optionPriceLOT1 / 1000); - let optionPriceETH2 = priceOption2_af / 1; - let optionPriceLOT2 = priceOption2_af / 1 / tokenPrice; - //console.log("Round off ETH price of option2", optionPriceETH2 / 1000); - //console.log("Round off LOT price of option2", optionPriceLOT2 / 1000); - let optionPriceETH3 = priceOption3_af / 1; - let optionPriceLOT3 = priceOption3_af / 1 / tokenPrice; - //console.log("Round off ETH price of option3", optionPriceETH3 / 1000); - //console.log("Round off LOT price of option3", optionPriceLOT3 / 1000); - }); -}); + await plotusToken.transfer(user4, toWei(40000)); + await plotusToken.approve(allMarkets.address, toWei(100000), { from: user4 }); + functionSignature = encode3("depositAndPlacePrediction(uint,uint,address,uint64,uint256)", toWei(40000), 9, plotusToken.address, 40000*1e8, 3); + await signAndExecuteMetaTx( + privateKeyList[3], + user4, + functionSignature, + allMarkets, + "AM" + ); -contract("Market", async function([user1, user2, user3, user4, user5, user6, user7, user8, user9, user10]) { - it("5.Scenario 4 - Stake in LOT+ETH> minstake and time passed > min time passed", async () => { - let tokenPrice = 0.01; - let masterInstance = await OwnedUpgradeabilityProxy.deployed(); - masterInstance = await Master.at(masterInstance.address); - let plotusToken = await PlotusToken.deployed(); - let BLOTInstance = await BLOT.deployed(); - let MockchainLinkInstance = await MockchainLinkBTC.deployed(); - let plotusNewAddress = await masterInstance.getLatestAddress(web3.utils.toHex("PL")); - let plotusNewInstance = await Plotus.at(plotusNewAddress); - let marketConfig = await plotusNewInstance.marketUtility(); - marketConfig = await MarketConfig.at(marketConfig); - const openMarkets = await plotusNewInstance.getOpenMarkets(); - //console.log("marketType", openMarkets["_marketTypes"][4] / 1); - marketInstance = await Market.at(openMarkets["_openMarkets"][4]); - await marketConfig.setMockPriceFlag(false); - await increaseTime(10001); - assert.ok(marketInstance); + let optionPricePaams = await allMarkets.getMarketOptionPricingParams(9,1); + await increaseTimeTo(optionPricePaams[1]/1+29*3600); - await MockchainLinkInstance.setLatestAnswer(1195000000000); - let currentPriceAfter = await MockchainLinkInstance.latestAnswer(); - //console.log(currentPriceAfter / 1); - await marketInstance.setOptionRangesPublic(11900, 12000); - let priceOption1 = await marketInstance.getOptionPrice(1); - let priceOption2 = await marketInstance.getOptionPrice(2); - let priceOption3 = await marketInstance.getOptionPrice(3); - //console.log(priceOption1 / 1, priceOption2 / 1, priceOption3 / 1); - - await plotusToken.approve(tokenController.address, "10000000000000000000000"); - await marketInstance.placePrediction(plotusToken.address, "1000000000000000000000", 1, 1, { - from: user1, - }); - - await marketInstance.placePrediction(plotusToken.address, "100000000000000000000", 2, 1, { - from: user1, - }); - - await marketInstance.placePrediction(plotusToken.address, "100000000000000000000", 3, 1, { - from: user1, - }); - - await marketInstance.placePrediction("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", "1000000000000000000", 1, 1, { - value: "1000000000000000000", - from: user1, - }); - - await marketInstance.placePrediction("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", "10000000000000000000", 2, 1, { - value: "10000000000000000000", - from: user2, - }); - - await marketInstance.placePrediction("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", "5000000000000000000", 3, 1, { - value: "5000000000000000000", - from: user2, - }); - - await increaseTime(104400); - let currentPriceAfter_af = await MockchainLinkInstance.latestAnswer(); - //console.log(currentPriceAfter_af / 1); - let priceOption1_af = await marketInstance.getOptionPrice(1); - let priceOption2_af = await marketInstance.getOptionPrice(2); - let priceOption3_af = await marketInstance.getOptionPrice(3); - let optionPriceETH1 = priceOption1_af / 1; - let optionPriceLOT1 = priceOption1_af / tokenPrice; - //console.log("Round off ETH price of option1", optionPriceETH1 / 1000); - //console.log("Round off LOT price of option1", optionPriceLOT1 / 1000); - let optionPriceETH2 = priceOption2_af / 1; - let optionPriceLOT2 = priceOption2_af / 1 / tokenPrice; - //console.log("Round off ETH price of option2", optionPriceETH2 / 1000); - //console.log("Round off LOT price of option2", optionPriceLOT2 / 1000); - let optionPriceETH3 = priceOption3_af / 1; - let optionPriceLOT3 = priceOption3_af / 1 / tokenPrice; - //console.log("Round off ETH price of option3", optionPriceETH3 / 1000); - //console.log("Round off LOT price of option3", optionPriceLOT3 / 1000); + assert.equal(truncNumber((await marketConfig.getOptionPrice(9,1))/1e5), 0.19); + assert.equal(truncNumber((await marketConfig.getOptionPrice(9,2))/1e5), 0.16); + assert.equal(truncNumber((await marketConfig.getOptionPrice(9,3))/1e5), 0.63); }); -}); - -contract("Market", async function([user1, user2, user3, user4, user5, user6, user7, user8, user9, user10]) { - it("6.Scenario 5 - Stake in LOT+ETH> minstake and time passed > min time passed, max distance = 2", async () => { - let tokenPrice = 0.01; - let masterInstance = await OwnedUpgradeabilityProxy.deployed(); - masterInstance = await Master.at(masterInstance.address); - let plotusToken = await PlotusToken.deployed(); - let BLOTInstance = await BLOT.deployed(); - let MockchainLinkInstance = await MockchainLinkBTC.deployed(); - let plotusNewAddress = await masterInstance.getLatestAddress(web3.utils.toHex("PL")); - let plotusNewInstance = await Plotus.at(plotusNewAddress); - let marketConfig = await plotusNewInstance.marketUtility(); - marketConfig = await MarketConfig.at(marketConfig); - const openMarkets = await plotusNewInstance.getOpenMarkets(); - //console.log("marketType", openMarkets["_marketTypes"][4] / 1); - marketInstance = await Market.at(openMarkets["_openMarkets"][4]); - await marketConfig.setMockPriceFlag(false); - await increaseTime(10001); - assert.ok(marketInstance); - await MockchainLinkInstance.setLatestAnswer(1222000000000); - let currentPriceAfter = await MockchainLinkInstance.latestAnswer(); - //console.log(currentPriceAfter / 1); - await marketInstance.setOptionRangesPublic(11900, 12000); - let priceOption1 = await marketInstance.getOptionPrice(1); - let priceOption2 = await marketInstance.getOptionPrice(2); - let priceOption3 = await marketInstance.getOptionPrice(3); - //console.log(priceOption1 / 1, priceOption2 / 1, priceOption3 / 1); - - - - await plotusToken.approve(tokenController.address, "10000000000000000000000"); - await marketInstance.placePrediction(plotusToken.address, "1000000000000000000000", 1, 1, { - from: user1, - }); - - await marketInstance.placePrediction(plotusToken.address, "100000000000000000000", 2, 1, { - from: user1, - }); - - await marketInstance.placePrediction(plotusToken.address, "100000000000000000000", 3, 1, { - from: user1, - }); - - await marketInstance.placePrediction("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", "1000000000000000000", 1, 1, { - value: "1000000000000000000", - from: user1, - }); - - await marketInstance.placePrediction("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", "10000000000000000000", 2, 1, { - value: "10000000000000000000", - from: user2, - }); - - await marketInstance.placePrediction("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", "5000000000000000000", 3, 1, { - value: "5000000000000000000", - from: user2, - }); - - await increaseTime(104400); - let currentPriceAfter_af = await MockchainLinkInstance.latestAnswer(); - //console.log(currentPriceAfter_af / 1); - let priceOption1_af = await marketInstance.getOptionPrice(1); - let priceOption2_af = await marketInstance.getOptionPrice(2); - let priceOption3_af = await marketInstance.getOptionPrice(3); - let optionPriceETH1 = priceOption1_af / 1; - let optionPriceLOT1 = priceOption1_af / tokenPrice; - //console.log("Round off ETH price of option1", optionPriceETH1 / 1000); - //console.log("Round off LOT price of option1", optionPriceLOT1 / 1000); - let optionPriceETH2 = priceOption2_af / 1; - let optionPriceLOT2 = priceOption2_af / 1 / tokenPrice; - //console.log("Round off ETH price of option2", optionPriceETH2 / 1000); - //console.log("Round off LOT price of option2", optionPriceLOT2 / 1000); - let optionPriceETH3 = priceOption3_af / 1; - let optionPriceLOT3 = priceOption3_af / 1 / tokenPrice; - //console.log("Round off ETH price of option3", optionPriceETH3 / 1000); - //console.log("Round off LOT price of option3", optionPriceLOT3 / 1000); + it("4.Scenario 4 - Stake > minstakes and time passed > min time passed max distance = 2", async () => { + let expireT = await allMarkets.getMarketData(9); + + await increaseTimeTo(expireT[5]); + + await allMarkets.createMarket(0, 2); + + + await plotusToken.transfer(user2, toWei(10000)); + await plotusToken.approve(allMarkets.address, toWei(100000), { from: user2 }); + let functionSignature = encode3("depositAndPlacePrediction(uint,uint,address,uint64,uint256)", toWei(10000), 10, plotusToken.address, 10000*1e8, 1); + await signAndExecuteMetaTx( + privateKeyList[1], + user2, + functionSignature, + allMarkets, + "AM" + ); + + await plotusToken.transfer(user3, toWei(5000)); + await plotusToken.approve(allMarkets.address, toWei(100000), { from: user3 }); + functionSignature = encode3("depositAndPlacePrediction(uint,uint,address,uint64,uint256)", toWei(5000), 10, plotusToken.address, 5000*1e8, 2); + await signAndExecuteMetaTx( + privateKeyList[2], + user3, + functionSignature, + allMarkets, + "AM" + ); + + await plotusToken.transfer(user4, toWei(40000)); + await plotusToken.approve(allMarkets.address, toWei(100000), { from: user4 }); + functionSignature = encode3("depositAndPlacePrediction(uint,uint,address,uint64,uint256)", toWei(40000), 10, plotusToken.address, 40000*1e8, 3); + await signAndExecuteMetaTx( + privateKeyList[3], + user4, + functionSignature, + allMarkets, + "AM" + ); + await MockchainLinkInstance.setLatestAnswer(1225000000000); + let optionPricePaams = await allMarkets.getMarketOptionPricingParams(10,1); + await increaseTimeTo(optionPricePaams[1]/1+29*3600); + + + assert.equal(truncNumber((await marketConfig.getOptionPrice(10,1))/1e5), 0.17); + assert.equal(truncNumber((await marketConfig.getOptionPrice(10,2))/1e5), 0.13); + assert.equal(truncNumber((await marketConfig.getOptionPrice(10,3))/1e5), 0.68); }); + }); diff --git a/test/21_weeklyMarketOptionPriceManual.js b/test/21_weeklyMarketOptionPriceManual.js new file mode 100644 index 000000000..0da87bec5 --- /dev/null +++ b/test/21_weeklyMarketOptionPriceManual.js @@ -0,0 +1,264 @@ +const { assert } = require("chai"); +const OwnedUpgradeabilityProxy = artifacts.require("OwnedUpgradeabilityProxy"); +const Master = artifacts.require("Master"); +const TokenController = artifacts.require("TokenController"); +const PlotusToken = artifacts.require("MockPLOT"); +const MarketConfig = artifacts.require("MockConfig"); +const BLOT = artifacts.require("BLOT"); +const Governance = artifacts.require("Governance"); +const MemberRoles = artifacts.require("MemberRoles"); +const ProposalCategory = artifacts.require("ProposalCategory"); +const AllMarkets = artifacts.require("AllMarkets"); +const increaseTime = require("./utils/increaseTime.js").increaseTime; +const increaseTimeTo = require("./utils/increaseTime.js").increaseTimeTo; +const { encode, encode1,encode3 } = require("./utils/encoder.js"); +const signAndExecuteMetaTx = require("./utils/signAndExecuteMetaTx.js").signAndExecuteMetaTx; +const { toHex, toWei, toChecksumAddress } = require("./utils/ethTools"); +const latestTime = require("./utils/latestTime.js").latestTime; +let privateKeyList = ["fb437e3e01939d9d4fef43138249f23dc1d0852e69b0b5d1647c087f869fabbd","7c85a1f1da3120c941b83d71a154199ee763307683f206b98ad92c3b4e0af13e","ecc9b35bf13bd5459350da564646d05c5664a7476fe5acdf1305440f88ed784c","f4470c3fca4dbef1b2488d016fae25978effc586a1f83cb29ac8cb6ab5bc2d50","141319b1a84827e1046e93741bf8a9a15a916d49684ab04925ac4ce4573eea23","d54b606094287758dcf19064a8d91c727346aadaa9388732e73c4315b7c606f9","49030e42ce4152e715a7ddaa10e592f8e61d00f70ef11f48546711f159d985df","b96761b1e7ebd1e8464a78a98fe52f53ce6035c32b4b2b12307a629a551ff7cf","d4786e2581571c863c7d12231c3afb6d4cef390c0ac9a24b243293721d28ea95","ed28e3d3530544f1cf2b43d1956b7bd13b63c612d963a8fb37387aa1a5e11460","05b127365cf115d4978a7997ee98f9b48f0ddc552b981c18aa2ee1b3e6df42c6","9d11dd6843f298b01b34bd7f7e4b1037489871531d14b58199b7cba1ac0841e6","f79e90fa4091de4fc2ec70f5bf67b24393285c112658e0d810e6bd711387fbb9","99f1fc0f09230ce745b6a256ba7082e6e51a2907abda3d9e735a5c8188bb4ba1","477f86cce983b9c91a36fdcd4a7ce21144a08dee9b1aafb91b9c70e57f717ce6","b03d2e6bb4a7d71c66a66ff9e9c93549cae4b593f634a4ea2a1f79f94200f5b4","9ddc0f53a81e631dcf39d5155f41ec12ed551b731efc3224f410667ba07b37dc","cf087ff9ae7c9954ad8612d071e5cdf34a6024ee1ae477217639e63a802a53dd","b64f62b94babb82cc78d3d1308631ae221552bb595202fc1d267e1c29ce7ba60","a91e24875f8a534497459e5ccb872c4438be3130d8d74b7e1104c5f94cdcf8c2","4f49f3d029eeeb3fed14d59625acd088b6b34f3b41c527afa09d29e4a7725c32","179795fd7ac7e7efcba3c36d539a1e8659fb40d77d0a3fab2c25562d99793086","4ba37d0b40b879eceaaca2802a1635f2e6d86d5c31e3ff2d2fd13e68dd2a6d3d","6b7f5dfba9cd3108f1410b56f6a84188eee23ab48a3621b209a67eea64293394","870c540da9fafde331a3316cee50c17ad76ddb9160b78b317bef2e6f6fc4bac0","470b4cccaea895d8a5820aed088357e380d66b8e7510f0a1ea9b575850160241","8a55f8942af0aec1e0df3ab328b974a7888ffd60ded48cc6862013da0f41afbc","2e51e8409f28baf93e665df2a9d646a1bf9ac8703cbf9a6766cfdefa249d5780","99ef1a23e95910287d39493d8d9d7d1f0b498286f2b1fdbc0b01495f10cf0958","6652200c53a4551efe2a7541072d817562812003f9d9ef0ec17995aa232378f8","39c6c01194df72dda97da2072335c38231ced9b39afa280452afcca901e73643","12097e411d948f77b7b6fa4656c6573481c1b4e2864c1fca9d5b296096707c45","cbe53bf1976aee6cec830a848c6ac132def1503cffde82ccfe5bd15e75cbaa72","eeab5dcfff92dbabb7e285445aba47bd5135a4a3502df59ac546847aeb5a964f","5ea8279a578027abefab9c17cef186cccf000306685e5f2ee78bdf62cae568dd","0607767d89ad9c7686dbb01b37248290b2fa7364b2bf37d86afd51b88756fe66","e4fd5f45c08b52dae40f4cdff45e8681e76b5af5761356c4caed4ca750dc65cd","145b1c82caa2a6d703108444a5cf03e9cb8c3cd3f19299582a564276dbbba734","736b22ec91ae9b4b2b15e8d8c220f6c152d4f2228f6d46c16e6a9b98b4733120","ac776cb8b40f92cdd307b16b83e18eeb1fbaa5b5d6bd992b3fda0b4d6de8524c","65ba30e2202fdf6f37da0f7cfe31dfb5308c9209885aaf4cef4d572fd14e2903","54e8389455ec2252de063e83d3ce72529d674e6d2dc2070661f01d4f76b63475","fbbbfb525dd0255ee332d51f59648265aaa20c2e9eff007765cf4d4a6940a849","8de5e418f34d04f6ea947ce31852092a24a705862e6b810ca9f83c2d5f9cda4d","ea6040989964f012fd3a92a3170891f5f155430b8bbfa4976cde8d11513b62d9","14d94547b5deca767137fbd14dae73e888f3516c742fad18b83be333b38f0b88","47f05203f6368d56158cda2e79167777fc9dcb0c671ef3aabc205a1636c26a29"]; +let nullAddress = "0x0000000000000000000000000000000000000000"; +truncNumber = (n) => Math.trunc(n * Math.pow(10, 2)) / Math.pow(10, 2); +let masterInstance,plotusToken,BLOTInstance,allMarkets,gv,mr,pc; + +contract("Market", async function([user1, user2, user3, user4]) { + + before(async function () { + masterInstance = await OwnedUpgradeabilityProxy.deployed(); + masterInstance = await Master.at(masterInstance.address); + plotusToken = await PlotusToken.deployed(); + BLOTInstance = await BLOT.deployed(); + allMarkets = await AllMarkets.at(await masterInstance.getLatestAddress(web3.utils.toHex("AM"))); + marketConfig = await MarketConfig.at(await masterInstance.getLatestAddress(web3.utils.toHex("MU"))); + + let address = await masterInstance.getLatestAddress(toHex("GV")); + gv = await Governance.at(address); + address = await masterInstance.getLatestAddress(toHex("PC")); + pc = await ProposalCategory.at(address); + address = await masterInstance.getLatestAddress(toHex("MR")); + mr = await MemberRoles.at(address); + + await marketConfig.setMockPriceFlag(false); + let expireT = await allMarkets.getMarketData(5); + + await increaseTimeTo(expireT[5]); + + let pId = (await gv.getProposalLength()).toNumber(); + await gv.createProposal("Proposal2", "Proposal2", "Proposal2", 0); //Pid 3 + await gv.categorizeProposal(pId, 15, 0); + let startTime = (await latestTime()) / 1 + 2 * 604800; + let actionHash = encode("addMarketCurrency(bytes32,address,uint8,uint8,uint32)", toHex("ETH/PLOT"), nullAddress, 8, 1, startTime); + await gv.submitProposalWithSolution(pId, "addNewMarketCurrency", actionHash); + await gv.submitVote(pId, 1, { from: user1 }); + await increaseTime(604810); + await gv.closeProposal(pId); + let actionStatus = await gv.proposalActionStatus(pId); + assert.equal(actionStatus / 1, 3); + await increaseTime(604810); + + await marketConfig.setFeedPriceForMarketType(toHex("ETH/PLOT"),1195000000000); + + }); + + it("1.Scenario 1 - Stake < minstakes and time passed < min time passed", async () => { + + await allMarkets.createMarket(2, 2); + await increaseTime(6*3600); + + let maxMin = await allMarkets.getMarketData(7); + + await plotusToken.transfer(user2, toWei(10000)); + await plotusToken.approve(allMarkets.address, toWei(100000), { from: user2 }); + let functionSignature = encode3("depositAndPlacePrediction(uint,uint,address,uint64,uint256)", toWei(10000), 7, plotusToken.address, 10000*1e8, 1); + await signAndExecuteMetaTx( + privateKeyList[1], + user2, + functionSignature, + allMarkets, + "AM" + ); + + await plotusToken.transfer(user3, toWei(2000)); + await plotusToken.approve(allMarkets.address, toWei(100000), { from: user3 }); + functionSignature = encode3("depositAndPlacePrediction(uint,uint,address,uint64,uint256)", toWei(2000), 7, plotusToken.address, 2000*1e8, 2); + await signAndExecuteMetaTx( + privateKeyList[2], + user3, + functionSignature, + allMarkets, + "AM" + ); + + await plotusToken.transfer(user4, toWei(5000)); + await plotusToken.approve(allMarkets.address, toWei(100000), { from: user4 }); + functionSignature = encode3("depositAndPlacePrediction(uint,uint,address,uint64,uint256)", toWei(5000), 7, plotusToken.address, 5000*1e8, 3); + await signAndExecuteMetaTx( + privateKeyList[3], + user4, + functionSignature, + allMarkets, + "AM" + ); + + + + assert.equal(await marketConfig.getOptionPrice(7,1), 25000); + assert.equal(await marketConfig.getOptionPrice(7,2), 50000); + assert.equal(await marketConfig.getOptionPrice(7,3), 25000); + }); + + it("2.Scenario 2 - Stake > minstakes and time passed < min time passed", async () => { + + + let expireT = await allMarkets.getMarketData(7); + + await increaseTimeTo(expireT[5]); + + await allMarkets.createMarket(2, 2); + + + + await plotusToken.transfer(user2, toWei(10000)); + await plotusToken.approve(allMarkets.address, toWei(100000), { from: user2 }); + let functionSignature = encode3("depositAndPlacePrediction(uint,uint,address,uint64,uint256)", toWei(10000), 8, plotusToken.address, 10000*1e8, 1); + await signAndExecuteMetaTx( + privateKeyList[1], + user2, + functionSignature, + allMarkets, + "AM" + ); + + await plotusToken.transfer(user3, toWei(5000)); + await plotusToken.approve(allMarkets.address, toWei(100000), { from: user3 }); + functionSignature = encode3("depositAndPlacePrediction(uint,uint,address,uint64,uint256)", toWei(5000), 8, plotusToken.address, 5000*1e8, 2); + await signAndExecuteMetaTx( + privateKeyList[2], + user3, + functionSignature, + allMarkets, + "AM" + ); + + await plotusToken.transfer(user4, toWei(40000)); + await plotusToken.approve(allMarkets.address, toWei(100000), { from: user4 }); + functionSignature = encode3("depositAndPlacePrediction(uint,uint,address,uint64,uint256)", toWei(40000), 8, plotusToken.address, 40000*1e8, 3); + await signAndExecuteMetaTx( + privateKeyList[3], + user4, + functionSignature, + allMarkets, + "AM" + ); + + let optionPricePaams = await allMarkets.getMarketOptionPricingParams(8,1); + await increaseTimeTo(optionPricePaams[1]/1+6*3600); + + + assert.equal(truncNumber((await marketConfig.getOptionPrice(8,1))/1e5), 0.19); + assert.equal(truncNumber((await marketConfig.getOptionPrice(8,2))/1e5), 0.16); + assert.equal(truncNumber((await marketConfig.getOptionPrice(8,3))/1e5), 0.63); + }); + + it("3.Scenario 3 - Stake > minstakes and time passed > min time passed", async () => { + + let expireT = await allMarkets.getMarketData(8); + + await increaseTimeTo(expireT[5]); + + await allMarkets.createMarket(2, 2); + + + await plotusToken.transfer(user2, toWei(10000)); + await plotusToken.approve(allMarkets.address, toWei(100000), { from: user2 }); + let functionSignature = encode3("depositAndPlacePrediction(uint,uint,address,uint64,uint256)", toWei(10000), 9, plotusToken.address, 10000*1e8, 1); + await signAndExecuteMetaTx( + privateKeyList[1], + user2, + functionSignature, + allMarkets, + "AM" + ); + + await plotusToken.transfer(user3, toWei(5000)); + await plotusToken.approve(allMarkets.address, toWei(100000), { from: user3 }); + functionSignature = encode3("depositAndPlacePrediction(uint,uint,address,uint64,uint256)", toWei(5000), 9, plotusToken.address, 5000*1e8, 2); + await signAndExecuteMetaTx( + privateKeyList[2], + user3, + functionSignature, + allMarkets, + "AM" + ); + + await plotusToken.transfer(user4, toWei(40000)); + await plotusToken.approve(allMarkets.address, toWei(100000), { from: user4 }); + functionSignature = encode3("depositAndPlacePrediction(uint,uint,address,uint64,uint256)", toWei(40000), 9, plotusToken.address, 40000*1e8, 3); + await signAndExecuteMetaTx( + privateKeyList[3], + user4, + functionSignature, + allMarkets, + "AM" + ); + + let optionPricePaams = await allMarkets.getMarketOptionPricingParams(9,1); + await increaseTimeTo(optionPricePaams[1]/1+29*3600); + + + + assert.equal(truncNumber((await marketConfig.getOptionPrice(9,1))/1e5), 0.19); + assert.equal(truncNumber((await marketConfig.getOptionPrice(9,2))/1e5), 0.16); + assert.equal(truncNumber((await marketConfig.getOptionPrice(9,3))/1e5), 0.63); + }); + + it("4.Scenario 4 - Stake > minstakes and time passed > min time passed max distance = 2", async () => { + let expireT = await allMarkets.getMarketData(9); + + await increaseTimeTo(expireT[5]); + + await allMarkets.createMarket(2, 2); + + + await plotusToken.transfer(user2, toWei(10000)); + await plotusToken.approve(allMarkets.address, toWei(100000), { from: user2 }); + let functionSignature = encode3("depositAndPlacePrediction(uint,uint,address,uint64,uint256)", toWei(10000), 10, plotusToken.address, 10000*1e8, 1); + await signAndExecuteMetaTx( + privateKeyList[1], + user2, + functionSignature, + allMarkets, + "AM" + ); + + await plotusToken.transfer(user3, toWei(5000)); + await plotusToken.approve(allMarkets.address, toWei(100000), { from: user3 }); + functionSignature = encode3("depositAndPlacePrediction(uint,uint,address,uint64,uint256)", toWei(5000), 10, plotusToken.address, 5000*1e8, 2); + await signAndExecuteMetaTx( + privateKeyList[2], + user3, + functionSignature, + allMarkets, + "AM" + ); + + await plotusToken.transfer(user4, toWei(40000)); + await plotusToken.approve(allMarkets.address, toWei(100000), { from: user4 }); + functionSignature = encode3("depositAndPlacePrediction(uint,uint,address,uint64,uint256)", toWei(40000), 10, plotusToken.address, 40000*1e8, 3); + await signAndExecuteMetaTx( + privateKeyList[3], + user4, + functionSignature, + allMarkets, + "AM" + ); + await marketConfig.setFeedPriceForMarketType(toHex("ETH/PLOT"),1225000000000); + let optionPricePaams = await allMarkets.getMarketOptionPricingParams(10,1); + await increaseTimeTo(optionPricePaams[1]/1+29*3600); + + + assert.equal(truncNumber((await marketConfig.getOptionPrice(10,1))/1e5), 0.17); + assert.equal(truncNumber((await marketConfig.getOptionPrice(10,2))/1e5), 0.13); + assert.equal(truncNumber((await marketConfig.getOptionPrice(10,3))/1e5), 0.68); + }); + +}); diff --git a/test/23_cummulativePrices.test.js b/test/23_cummulativePrices.test.js deleted file mode 100644 index c6f717625..000000000 --- a/test/23_cummulativePrices.test.js +++ /dev/null @@ -1,148 +0,0 @@ -const { assert } = require("chai"); -const OwnedUpgradeabilityProxy = artifacts.require("OwnedUpgradeabilityProxy"); -const Market = artifacts.require("MockMarket"); -const Plotus = artifacts.require("MarketRegistry"); -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 {toHex, toWei, toChecksumAddress} = require('./utils/ethTools'); -const gvProposal = require('./utils/gvProposal.js').gvProposalWithIncentiveViaTokenHolder; - -var initialPLOTPrice; -var initialEthPrice; -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; - 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 Markets 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("Should not allow to re initialize Utility after updating Implementation", async function() { - await assertRevert(marketConfig.initialize([user1, MockUniswapRouterInstance.address, plotusToken.address, mockUniswapFactory.address], user1)) - }); - - 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(); - }); - - it('Should not update market config address parameters if zero address', async function() { - let newUtility = await MarketUtility.new(); - let existingMarkets = await plotusNewInstance.getOpenMarkets(); - let actionHash = encode( - 'updateConfigAddressParameters(bytes8,address)', - toHex("UNIFAC"), - nullAddress - ); - let proposalId = await governance.getProposalLength(); - await gvProposal( - 21, - actionHash, - await MemberRoles.at(await masterInstance.getLatestAddress(toHex('MR'))), - governance, - 2, - 0 - ); - assert.notEqual(3, (await governance.proposalActionStatus(proposalId))/1); - await increaseTime(604800); - }); - - it("Check price of plot", async function() { - await increaseTime(3610); - await assertRevert(plotusNewInstance.createMarket(0,0)); - await marketConfig.setInitialCummulativePrice(); - await assertRevert(marketConfig.setInitialCummulativePrice()); - await mockUniswapV2Pair.sync(); - await increaseTime(3610); - await plotusNewInstance.createMarket(0,0); - let currentPrice = (await marketConfig.getPrice(mockUniswapV2Pair.address, toWei(1)))/1; - assert.equal(initialEthPrice, currentPrice/1e18); - await plotusNewInstance.createMarket(0,1); - await increaseTime(3610); - await mockUniswapV2Pair.sync(); - await plotusNewInstance.createMarket(0,0); - await increaseTime(3610); - await mockUniswapV2Pair.sync(); - currentPrice = (await marketConfig.getPrice(mockUniswapV2Pair.address, toWei(1)))/1; - assert.equal(initialEthPrice, currentPrice/1e18); - let plotPriceInEth = ((await marketConfig.getAssetPriceInETH(plotusToken.address))[0])/1; - assert.equal(initialEthPrice, plotPriceInEth/1e18); - let ethPriceInEth = ((await marketConfig.getAssetPriceInETH(ethAddress))[0])/1; - assert.equal(ethPriceInEth, 1); - }); - - it("Get asset price in PLOT", async function() { - let currentPrice = (await marketConfig.getValueAndMultiplierParameters(ethAddress, "1000000000000000000")) - assert.equal(initialPLOTPrice, currentPrice[1]/1e18); - currentPrice = (await marketConfig.getValueAndMultiplierParameters(plotusToken.address, "1000000000000000000")) - assert.equal(1, currentPrice[1]/1e18); - }); - -}); diff --git a/test/24_upgradedcreationincentive.test.js b/test/24_upgradedcreationincentive.test.js new file mode 100644 index 000000000..85c07cde1 --- /dev/null +++ b/test/24_upgradedcreationincentive.test.js @@ -0,0 +1,1274 @@ +const { assert } = require("chai"); +const sha3 = require("js-sha3").keccak_256; +const OwnedUpgradeabilityProxy = artifacts.require("OwnedUpgradeabilityProxy"); +const Master = artifacts.require("Master"); +const MemberRoles = artifacts.require("MemberRoles"); +const PlotusToken = artifacts.require("MockPLOT"); +const MarketUtility = artifacts.require("MockConfig"); +const MockConfig = artifacts.require("MockConfig"); +const Governance = artifacts.require("Governance"); +const GovernanceNew = artifacts.require("Governance"); +const ProposalCategory = artifacts.require("ProposalCategory"); +const TokenController = artifacts.require("MockTokenController"); +const AllMarkets = artifacts.require("MockAllMarkets"); +const MarketCreationRewards = artifacts.require("MarketCreationRewards"); +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; + +const to8Power = (number) => String(parseFloat(number) * 1e8); + +var initialPLOTPrice; +var initialEthPrice; +var eventData; +var incentivesGained = 0; +const ethAddress = "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE"; +var nullAddress = "0x0000000000000000000000000000"; + +contract("Market Creation Incentive", async function([ + user1, + user2, + user3, + user4, + user5, + user6, + user7, + user8, + user9, + user10, + user11, + user12, + user13, + user14, +]) { + let masterInstance, + plotusToken, + marketConfig, + tokenControllerAdd, + tokenController, + plotusNewAddress, + governance, + chainlinkGasAgg, + pc, + allMarkets, + marketIncentives, + marketId; + 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); + pc = await masterInstance.getLatestAddress(web3.utils.toHex("PC")); + pc = await ProposalCategory.at(pc); + marketConfig = await masterInstance.getLatestAddress(web3.utils.toHex("MU")); + marketConfig = await MockConfig.at(marketConfig); + allMarkets = await AllMarkets.at(await masterInstance.getLatestAddress(web3.utils.toHex("AM"))); + marketIncentives = await MarketCreationRewards.at(await masterInstance.getLatestAddress(web3.utils.toHex("MC"))); + }); + function findByTxHash(array1, txHash) { + let i; + for (i = array1.length - 1; i >= 0; i--) { + if (array1[i].transactionHash == txHash) { + return array1[i].returnValues; + } + } + return 0; + } + 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 revert if non proxy owner tries to call setMasterAddress()", async function() { + await assertRevert(allMarkets.setMasterAddress()); + }); + + it("Should revert if tries to call addInitialMarketTypesAndStart() after initialization", async function() { + await assertRevert(allMarkets.addInitialMarketTypesAndStart(1,user1,user1,user1)); + }); + + it("Should create Markets", async function() { + console.log("-====>", allMarkets.address); + await increaseTime(8 * 60 * 60); + let tx = await allMarkets.createMarket(0, 0); + + await assertRevert(allMarkets.createMarket(0, 0)); // Multiple same kind of markets can't exist at same time + let events = await marketIncentives.getPastEvents("allEvents", { fromBlock: 0, toBlock: "latest" }); + eventData = findByTxHash(events, tx.tx); + }); + + it("Scenario 1: Should be able to get reward pool share of market", async function() { + marketId = 8; + await increaseTime(4 * 3600); + await plotusToken.transfer(user2, toWei(1000)); + await plotusToken.approve(allMarkets.address, toWei(10000), { from: user2 }); + let tx = await allMarkets.createMarket(0, 0, { from: user2 }); + + await plotusToken.transfer(user7, toWei(10000)); + await plotusToken.approve(allMarkets.address, toWei(10000000), { from: user7 }); + + + await marketConfig.setNextOptionPrice(10); + await allMarkets.depositAndPlacePrediction(toWei(100), marketId, plotusToken.address, to8Power(100), 3, { from: user7 }); + await allMarkets.depositAndPlacePrediction(toWei(400), marketId, plotusToken.address, to8Power(400), 1, { from: user7 }); + // await allMarkets.depositAndPlacePrediction(toWei(100), marketId, plotusToken.address, to8Power(100), 1, { from: user7 }); + + let rewardPoolPlot = 99.95 + 66.66666666; + let events = await marketIncentives.getPastEvents("allEvents", { fromBlock: 0, toBlock: "latest" }); + eventData = findByTxHash(events, tx.tx); + let rewardPoolSharePerc = eventData.rewardPoolSharePerc; + assert.equal(rewardPoolSharePerc / 1, 50); + + await increaseTime(8 * 60 * 60); + await allMarkets.postResultMock(1, marketId); + await increaseTime(9 * 60 * 60); + + let oldBalance = parseFloat(await plotusToken.balanceOf(user2)); + tx = await marketIncentives.claimCreationReward(100, { from: user2 }); + let newBalance = parseFloat(await plotusToken.balanceOf(user2)); + assert.equal( + (newBalance / 1e18).toFixed(2), + (oldBalance / 1e18 + (rewardPoolPlot * rewardPoolSharePerc) / 10000).toFixed(2) + ); + }); + + it("Scenario 2: Should be able to get reward pool share of market", async function() { + marketId++; + await plotusToken.transfer(user2, toWei(25000)); + await plotusToken.approve(tokenController.address, toWei(10000000), { from: user2 }); + await tokenController.lock("0x534d", toWei(25000), 86400 * 30, { from: user2 }); + await increaseTime(4 * 3600); + let tx = await allMarkets.createMarket(0, 0, { from: user2 }); + + await plotusToken.transfer(user7, toWei(1000)); + await plotusToken.approve(allMarkets.address, toWei(10000000), { from: user7 }); + + + await marketConfig.setNextOptionPrice(10); + await allMarkets.depositAndPlacePrediction(toWei(100), marketId, plotusToken.address, to8Power(100), 3, { from: user7 }); + await allMarkets.depositAndPlacePrediction(toWei(400), marketId, plotusToken.address, to8Power(400), 1, { from: user7 }); + // await allMarkets.depositAndPlacePrediction(toWei(100), marketId, plotusToken.address, to8Power(100), 1, { from: user7 }); + + let rewardPoolPlot = 99.95 + 66.66666666; + let events = await marketIncentives.getPastEvents("allEvents", { fromBlock: 0, toBlock: "latest" }); + eventData = findByTxHash(events, tx.tx); + let rewardPoolSharePerc = eventData.rewardPoolSharePerc; + assert.equal(rewardPoolSharePerc / 1, 100); + + await increaseTime(8 * 60 * 60); + await allMarkets.postResultMock(1, marketId); + await increaseTime(9 * 60 * 60); + + let oldBalance = parseFloat(await plotusToken.balanceOf(user2)); + tx = await marketIncentives.claimCreationReward(100, { from: user2 }); + let newBalance = parseFloat(await plotusToken.balanceOf(user2)); + assert.equal( + (newBalance / 1e18).toFixed(2), + (oldBalance / 1e18 + (rewardPoolPlot * 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(user12, toWei(25000)); + // await plotusToken.approve(tokenController.address, toWei(10000000), { from: user12 }); + // await tokenController.lock("0x534d", toWei(25000), 86400 * 30, { from: user12 }); + // await chainlinkGasAgg.setLatestAnswer(450000); + // await increaseTime(8 * 3600); + // let tx = await allMarkets.createMarket(0, 0, { gasPrice: 450000, from: user12 }); + // marketId++; //12 + // await plotusToken.approve(allMarkets.address, toWei(10000000), { from: user13 }); + // await allMarkets.deposit(0, { from: user13, value: toWei(2) }); + // await allMarkets.placePrediction(marketId, ethAddress, to8Power(0.1), 3, { from: user13 }); + // await allMarkets.placePrediction(marketId, ethAddress, to8Power(1), 1, { from: user13 }); + // await plotusToken.transfer(user7, toWei(10000)); + // await plotusToken.approve(allMarkets.address, toWei(10000000), { from: user7 }); + // await allMarkets.deposit(toWei(100), { from: user7 }); + // await allMarkets.placePrediction(marketId, plotusToken.address, to8Power(100), 3, { from: user7 }); + // let rewardPoolEth = 0.1; + // let rewardPoolPlot = 99.95; + // let events = await marketIncentives.getPastEvents("allEvents", { fromBlock: 0, toBlock: "latest" }); + // eventData = findByTxHash(events, tx.tx); + // let gasUsed = eventData.gasUsed; + // let maxGas = 100 * 10 ** 9; + // let gasPrice = Math.min(maxGas, 450000 * 1.25, 450000); + // 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(8 * 60 * 60); + // await allMarkets.postResultMock(1, marketId); + // await increaseTime(8 * 60 * 60); + // let oldBalance = parseFloat(await plotusToken.balanceOf(user12)); + // let oldBalanceEth = parseFloat(await web3.eth.getBalance(user12)); + // tx = await marketIncentives.claimCreationReward(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)); + // }); + + it("Scenario 3: Should be able to get reward pool share of market", async function() { + marketId++; + await plotusToken.transfer(user12, toWei(51000)); + await plotusToken.approve(tokenController.address, toWei(10000000), { from: user12 }); + await plotusToken.approve(allMarkets.address, toWei(10000000), { from: user12 }); + await tokenController.lock("0x534d", toWei(50000), 86400 * 30, { from: user12 }); + await increaseTime(4 * 3600); + let tx = await allMarkets.createMarket(0, 0, { from: user12 }); + + await plotusToken.transfer(user7, toWei(1000)); + await plotusToken.approve(allMarkets.address, toWei(10000000), { from: user7 }); + + + await marketConfig.setNextOptionPrice(10); + await allMarkets.depositAndPlacePrediction(toWei(100), marketId, plotusToken.address, to8Power(100), 3, { from: user7 }); + await allMarkets.depositAndPlacePrediction(toWei(400), marketId, plotusToken.address, to8Power(400), 1, { from: user7 }); + // await allMarkets.depositAndPlacePrediction(toWei(100), marketId, plotusToken.address, to8Power(100), 1, { from: user7 }); + + let rewardPoolPlot = 99.95 + 66.66666666; + let events = await marketIncentives.getPastEvents("allEvents", { fromBlock: 0, toBlock: "latest" }); + eventData = findByTxHash(events, tx.tx); + let rewardPoolSharePerc = eventData.rewardPoolSharePerc; + assert.equal(rewardPoolSharePerc / 1, 150); + + await increaseTime(8 * 60 * 60); + await allMarkets.postResultMock(1, marketId); + await increaseTime(9 * 60 * 60); + + let oldBalance = parseFloat(await plotusToken.balanceOf(user12)); + tx = await marketIncentives.claimCreationReward(100, { from: user12 }); + let newBalance = parseFloat(await plotusToken.balanceOf(user12)); + assert.equal( + (newBalance / 1e18).toFixed(2), + (oldBalance / 1e18 + (rewardPoolPlot * 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, toWei(10000000), { from: user3 }); + // await tokenController.lock("0x534d", toWei(50000), 86400 * 30, { from: user3 }); + // await chainlinkGasAgg.setLatestAnswer(450000); + // await increaseTime(4 * 3600); + // let tx = await allMarkets.createMarket(0, 0, { gasPrice: 450000, from: user3 }); + // marketId++; //13 + // await allMarkets.deposit(0, { from: user12, value: 100000000000000000 }); + // await allMarkets.placePrediction(marketId, ethAddress, to8Power(0.1), 3, { + // from: user12, + // }); + // await plotusToken.transfer(user7, toWei(10000)); + // await plotusToken.approve(allMarkets.address, toWei(10000000), { from: user7 }); + // await allMarkets.deposit(toWei(10), { from: user7 }); + // await allMarkets.placePrediction(marketId, plotusToken.address, toWei(10) / 1e10, 3, { + // from: user7, + // }); + // let rewardPoolEth = 0.1; + // let rewardPoolPlot = 9.95; + // let events = await marketIncentives.getPastEvents("allEvents", { fromBlock: 0, toBlock: "latest" }); + // eventData = findByTxHash(events, tx.tx); + // let gasUsed = eventData.gasUsed; + // let maxGas = 100 * 10 ** 9; + // let gasPrice = Math.min(maxGas, 450000 * 1.25, 450000); + // 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, 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(8 * 60 * 60); + // await allMarkets.postResultMock(1, marketId); + // await increaseTime(8 * 60 * 60); + // let oldBalance = parseFloat(await plotusToken.balanceOf(user3)); + // let oldBalanceEth = parseFloat(await web3.eth.getBalance(user3)); + // tx = await marketIncentives.claimCreationReward(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 * 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 reward pool share of market", async function() { + marketId++; + await plotusToken.transfer(user4, toWei(61000)); + await plotusToken.approve(tokenController.address, toWei(10000000), { from: user4 }); + await plotusToken.approve(allMarkets.address, toWei(10000000), { from: user4 }); + await tokenController.lock("0x534d", toWei(60000), 86400 * 30, { from: user4 }); + await increaseTime(4 * 3600); + let tx = await allMarkets.createMarket(0, 0, { from: user4 }); + + await plotusToken.transfer(user7, toWei(1000)); + await plotusToken.approve(allMarkets.address, toWei(10000000), { from: user7 }); + + + await marketConfig.setNextOptionPrice(10); + await allMarkets.depositAndPlacePrediction(toWei(100), marketId, plotusToken.address, to8Power(100), 3, { from: user7 }); + await allMarkets.depositAndPlacePrediction(toWei(400), marketId, plotusToken.address, to8Power(400), 1, { from: user7 }); + // await allMarkets.depositAndPlacePrediction(toWei(100), marketId, plotusToken.address, to8Power(100), 1, { from: user7 }); + + let rewardPoolPlot = 99.95 + 66.66666666; + let events = await marketIncentives.getPastEvents("allEvents", { fromBlock: 0, toBlock: "latest" }); + eventData = findByTxHash(events, tx.tx); + let rewardPoolSharePerc = eventData.rewardPoolSharePerc; + assert.equal(rewardPoolSharePerc / 1, 150); + + await increaseTime(8 * 60 * 60); + await allMarkets.postResultMock(1, marketId); + await increaseTime(9 * 60 * 60); + + let oldBalance = parseFloat(await plotusToken.balanceOf(user4)); + tx = await marketIncentives.claimCreationReward(100, { from: user4 }); + let newBalance = parseFloat(await plotusToken.balanceOf(user4)); + assert.equal( + (newBalance / 1e18).toFixed(2), + (oldBalance / 1e18 + (rewardPoolPlot * 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() { + // await plotusToken.transfer(user4, toWei(60000)); + // await plotusToken.approve(tokenController.address, toWei(10000000), { from: user4 }); + // await tokenController.lock("0x534d", toWei(60000), 86400 * 30, { from: user4 }); + // await chainlinkGasAgg.setLatestAnswer(450000); + // await increaseTime(4 * 3600); + // let tx = await allMarkets.createMarket(0, 0, { gasPrice: 450000, from: user4 }); + // marketId++; //14 + // let events = await marketIncentives.getPastEvents("allEvents", { fromBlock: 0, toBlock: "latest" }); + // eventData = findByTxHash(events, tx.tx); + // await allMarkets.deposit(0, { from: user13, value: toWei(2) }); + // await allMarkets.placePrediction(marketId, ethAddress, to8Power(0.1), 3, { from: user13 }); + // await allMarkets.placePrediction(marketId, ethAddress, to8Power(1), 1, { from: user13 }); + // await plotusToken.transfer(user7, toWei(10000)); + // await plotusToken.approve(allMarkets.address, toWei(10000000), { from: user7 }); + // await allMarkets.deposit(toWei(100), { from: user7 }); + // await allMarkets.placePrediction(marketId, plotusToken.address, to8Power(100), 3, { from: user7 }); + // let rewardPoolEth = 0.1; + // let rewardPoolPlot = 99.95; + // let gasUsed = eventData.gasUsed; + // let maxGas = 100 * 10 ** 9; + // let gasPrice = Math.min(maxGas, 450000 * 1.25, 450000); + // 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, 150); + // assert.equal(eventData.plotIncentive / 1, worthInPLOT[1] / 1); + // await increaseTime(8 * 60 * 60); + // await allMarkets.postResultMock(1, marketId); + // await increaseTime(8 * 60 * 60); + // let oldBalance = parseFloat(await plotusToken.balanceOf(user4)); + // let oldBalanceEth = parseFloat(await web3.eth.getBalance(user4)); + // tx = await marketIncentives.claimCreationReward(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 * 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 reward pool share of market", async function() { + marketId++; + await plotusToken.transfer(user5, toWei(110000)); + await plotusToken.approve(tokenController.address, toWei(10000000), { from: user5 }); + await plotusToken.approve(allMarkets.address, toWei(10000000), { from: user5 }); + await tokenController.lock("0x534d", toWei(100000), 86400 * 30, { from: user5 }); + await increaseTime(4 * 3600); + let tx = await allMarkets.createMarket(0, 0, { from: user5 }); + + await plotusToken.transfer(user7, toWei(1000)); + await plotusToken.approve(allMarkets.address, toWei(10000000), { from: user7 }); + + + await marketConfig.setNextOptionPrice(10); + await allMarkets.depositAndPlacePrediction(toWei(100), marketId, plotusToken.address, to8Power(100), 3, { from: user7 }); + await allMarkets.depositAndPlacePrediction(toWei(400), marketId, plotusToken.address, to8Power(400), 1, { from: user7 }); + // await allMarkets.depositAndPlacePrediction(toWei(100), marketId, plotusToken.address, to8Power(100), 1, { from: user7 }); + + let rewardPoolPlot = 99.95 + 66.66666666; + let events = await marketIncentives.getPastEvents("allEvents", { fromBlock: 0, toBlock: "latest" }); + eventData = findByTxHash(events, tx.tx); + let rewardPoolSharePerc = eventData.rewardPoolSharePerc; + assert.equal(rewardPoolSharePerc / 1, 250); + + await increaseTime(8 * 60 * 60); + await allMarkets.postResultMock(1, marketId); + await increaseTime(9 * 60 * 60); + + let oldBalance = parseFloat(await plotusToken.balanceOf(user5)); + tx = await marketIncentives.claimCreationReward(100, { from: user5 }); + let newBalance = parseFloat(await plotusToken.balanceOf(user5)); + assert.equal( + (newBalance / 1e18).toFixed(2), + (oldBalance / 1e18 + (rewardPoolPlot * 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() { + // await plotusToken.transfer(user5, toWei(100000)); + // await plotusToken.approve(tokenController.address, toWei(10000000), { from: user5 }); + // await tokenController.lock("0x534d", toWei(100000), 86400 * 30, { from: user5 }); + // await chainlinkGasAgg.setLatestAnswer(450000); + // await increaseTime(4 * 3600); + // let tx = await allMarkets.createMarket(0, 0, { gasPrice: 450000, from: user5 }); + // marketId++; //15 + // await plotusToken.transfer(user7, toWei(10000)); + // await plotusToken.approve(allMarkets.address, toWei(10000000), { from: user7 }); + // await allMarkets.deposit(0, { from: user12, value: toWei(0.1) }); + // await allMarkets.deposit(toWei(100), { from: user7 }); + // await allMarkets.placePrediction(marketId, ethAddress, to8Power(0.1), 3, { from: user12 }); + // await allMarkets.placePrediction(marketId, plotusToken.address, to8Power(100), 3, { from: user7 }); + // let rewardPoolEth = 0.1; + // let rewardPoolPlot = 99.95; + // let events = await marketIncentives.getPastEvents("allEvents", { fromBlock: 0, toBlock: "latest" }); + // eventData = findByTxHash(events, tx.tx); + // let gasUsed = eventData.gasUsed; + // let maxGas = 100 * 10 ** 9; + // let gasPrice = Math.min(maxGas, 450000 * 1.25, 450000); + // 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, 250); + // assert.equal(eventData.plotIncentive / 1, worthInPLOT[1] / 1); + // await increaseTime(8 * 60 * 60); + // await allMarkets.postResultMock(1, marketId); + // await increaseTime(8 * 60 * 60); + // let oldBalance = parseFloat(await plotusToken.balanceOf(user5)); + // let oldBalanceEth = parseFloat(await web3.eth.getBalance(user5)); + // tx = await marketIncentives.claimCreationReward(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 * 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 reward pool share of market", async function() { + marketId++; + await plotusToken.transfer(user6, toWei(151000)); + await plotusToken.approve(tokenController.address, toWei(10000000), { from: user6 }); + await plotusToken.approve(allMarkets.address, toWei(10000000), { from: user6 }); + await tokenController.lock("0x534d", toWei(150000), 86400 * 30, { from: user6 }); + await increaseTime(4 * 3600); + let tx = await allMarkets.createMarket(0, 0, { from: user6 }); + + await plotusToken.transfer(user7, toWei(1000)); + await plotusToken.approve(allMarkets.address, toWei(10000000), { from: user7 }); + + + await marketConfig.setNextOptionPrice(10); + await allMarkets.depositAndPlacePrediction(toWei(100), marketId, plotusToken.address, to8Power(100), 3, { from: user7 }); + await allMarkets.depositAndPlacePrediction(toWei(400), marketId, plotusToken.address, to8Power(400), 1, { from: user7 }); + // await allMarkets.depositAndPlacePrediction(toWei(100), marketId, plotusToken.address, to8Power(100), 1, { from: user7 }); + + let rewardPoolPlot = 99.95 + 66.66666666; + let events = await marketIncentives.getPastEvents("allEvents", { fromBlock: 0, toBlock: "latest" }); + eventData = findByTxHash(events, tx.tx); + let rewardPoolSharePerc = eventData.rewardPoolSharePerc; + assert.equal(rewardPoolSharePerc / 1, 350); + + await increaseTime(8 * 60 * 60); + await allMarkets.postResultMock(1, marketId); + await increaseTime(9 * 60 * 60); + + let oldBalance = parseFloat(await plotusToken.balanceOf(user6)); + tx = await marketIncentives.claimCreationReward(100, { from: user6 }); + let newBalance = parseFloat(await plotusToken.balanceOf(user6)); + assert.equal( + (newBalance / 1e18).toFixed(2), + (oldBalance / 1e18 + (rewardPoolPlot * 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() { + // await plotusToken.transfer(user6, toWei(150000)); + // await plotusToken.approve(tokenController.address, toWei(10000000), { from: user6 }); + // await tokenController.lock("0x534d", toWei(150000), 86400 * 30, { from: user6 }); + // await chainlinkGasAgg.setLatestAnswer(450000); + // await increaseTime(4 * 3600); + // let tx = await allMarkets.createMarket(0, 0, { gasPrice: 450000, from: user6 }); + // marketId++; + // await plotusToken.transfer(user7, toWei(10000)); + // await plotusToken.approve(allMarkets.address, toWei(10000000), { from: user7 }); + // await allMarkets.deposit(toWei(100), { from: user7, value: toWei(0.1) }); + // await allMarkets.placePrediction(marketId, ethAddress, to8Power(0.1), 3, { + // from: user7, + // }); + // await allMarkets.placePrediction(marketId, plotusToken.address, to8Power(100), 3, { + // from: user7, + // }); + // let rewardPoolEth = 0.1; + // let rewardPoolPlot = 99.95; + // let events = await marketIncentives.getPastEvents("allEvents", { fromBlock: 0, toBlock: "latest" }); + // eventData = findByTxHash(events, tx.tx); + // let gasUsed = eventData.gasUsed; + // let maxGas = 100 * 10 ** 9; + // let gasPrice = Math.min(maxGas, 450000 * 1.25, 450000); + // 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, 350); + // assert.equal(eventData.plotIncentive / 1, worthInPLOT[1] / 1); + // await increaseTime(8 * 60 * 60); + // await allMarkets.postResultMock(1, marketId); + // await increaseTime(8 * 60 * 60); + // let oldBalance = parseFloat(await plotusToken.balanceOf(user6)); + // let oldBalanceEth = parseFloat(await web3.eth.getBalance(user6)); + // tx = await marketIncentives.claimCreationReward(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 * rewardPoolSharePerc) / 10000).toFixed(2) + // ); + // assert.equal((newBalanceEth / 1e18).toFixed(2), (oldBalanceEth / 1e18 + (rewardPoolEth * rewardPoolSharePerc) / 10000).toFixed(2)); + // }); + it("Scenario 7: Should be able to get reward pool share of market", async function() { + marketId++; + await plotusToken.transfer(user8, toWei(151000)); + await plotusToken.approve(tokenController.address, toWei(10000000), { from: user8 }); + await plotusToken.approve(allMarkets.address, toWei(10000000), { from: user8 }); + await tokenController.lock("0x534d", toWei(150000), 86400 * 30, { from: user8 }); + await increaseTime(4 * 3600); + let tx = await allMarkets.createMarket(0, 0, { from: user8 }); + + await plotusToken.transfer(user7, toWei(1000)); + await plotusToken.approve(allMarkets.address, toWei(10000000), { from: user7 }); + + + await marketConfig.setNextOptionPrice(10); + await allMarkets.depositAndPlacePrediction(toWei(100), marketId, plotusToken.address, to8Power(100), 3, { from: user7 }); + await allMarkets.depositAndPlacePrediction(toWei(400), marketId, plotusToken.address, to8Power(400), 1, { from: user7 }); + // await allMarkets.depositAndPlacePrediction(toWei(100), marketId, plotusToken.address, to8Power(100), 1, { from: user7 }); + + let rewardPoolPlot = 99.95 + 66.66666666; + let events = await marketIncentives.getPastEvents("allEvents", { fromBlock: 0, toBlock: "latest" }); + eventData = findByTxHash(events, tx.tx); + let rewardPoolSharePerc = eventData.rewardPoolSharePerc; + assert.equal(rewardPoolSharePerc / 1, 350); + + await increaseTime(8 * 60 * 60); + await allMarkets.postResultMock(1, marketId); + await increaseTime(9 * 60 * 60); + + let oldBalance = parseFloat(await plotusToken.balanceOf(user8)); + tx = await marketIncentives.claimCreationReward(100, { from: user8 }); + let newBalance = parseFloat(await plotusToken.balanceOf(user8)); + assert.equal( + (newBalance / 1e18).toFixed(2), + (oldBalance / 1e18 + (rewardPoolPlot * rewardPoolSharePerc) / 10000).toFixed(2) + ); + }); + // 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, toWei(10000000), { from: user8 }); + // await tokenController.lock("0x534d", toWei(150000), 86400 * 30, { from: user8 }); + // await chainlinkGasAgg.setLatestAnswer(450000); + // await increaseTime(4 * 3600); + // let tx = await allMarkets.createMarket(0, 0, { gasPrice: 450000, from: user8 }); + // marketId++; + // let rewardPoolEth = 0; + // let rewardPoolPlot = 0; + // let events = await marketIncentives.getPastEvents("allEvents", { fromBlock: 0, toBlock: "latest" }); + // eventData = findByTxHash(events, tx.tx); + // let gasUsed = eventData.gasUsed; + // let maxGas = 100 * 10 ** 9; + // let gasPrice = Math.min(maxGas, 450000 * 1.25, 450000); + // 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, 350); + // assert.equal(eventData.plotIncentive / 1, worthInPLOT[1] / 1); + // await increaseTime(8 * 60 * 60); + // await allMarkets.postResultMock(1, marketId); + // await increaseTime(8 * 60 * 60); + // let oldBalance = parseFloat(await plotusToken.balanceOf(user8)); + // let oldBalanceEth = parseFloat(await web3.eth.getBalance(user8)); + // tx = await marketIncentives.claimCreationReward(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 * rewardPoolSharePerc) / 10000).toFixed(2) + // ); + // 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() { + marketId++; + await plotusToken.transfer(user14, toWei(501000)); + await plotusToken.approve(tokenController.address, toWei(10000000), { from: user14 }); + await plotusToken.approve(allMarkets.address, toWei(10000000), { from: user14 }); + await tokenController.lock("0x534d", toWei(500000), 86400 * 30, { from: user14 }); + await increaseTime(4 * 3600); + let tx = await allMarkets.createMarket(0, 0, { from: user14 }); + + await plotusToken.transfer(user7, toWei(1000)); + await plotusToken.approve(allMarkets.address, toWei(10000000), { from: user7 }); + + + await marketConfig.setNextOptionPrice(10); + await allMarkets.depositAndPlacePrediction(toWei(100), marketId, plotusToken.address, to8Power(100), 3, { from: user7 }); + await allMarkets.depositAndPlacePrediction(toWei(400), marketId, plotusToken.address, to8Power(400), 1, { from: user7 }); + // await allMarkets.depositAndPlacePrediction(toWei(100), marketId, plotusToken.address, to8Power(100), 1, { from: user7 }); + + let rewardPoolPlot = 99.95 + 66.66666666; + let events = await marketIncentives.getPastEvents("allEvents", { fromBlock: 0, toBlock: "latest" }); + eventData = findByTxHash(events, tx.tx); + let rewardPoolSharePerc = eventData.rewardPoolSharePerc; + assert.equal(rewardPoolSharePerc / 1, 500); + + await increaseTime(8 * 60 * 60); + await allMarkets.postResultMock(1, marketId); + await increaseTime(9 * 60 * 60); + + let oldBalance = parseFloat(await plotusToken.balanceOf(user14)); + tx = await marketIncentives.claimCreationReward(100, { from: user14 }); + let newBalance = parseFloat(await plotusToken.balanceOf(user14)); + assert.equal( + (newBalance / 1e18).toFixed(2), + (oldBalance / 1e18 + (rewardPoolPlot * 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, toWei(10000000), { from: user14 }); + // await tokenController.lock("0x534d", toWei(500000), 86400 * 30, { from: user14 }); + // await chainlinkGasAgg.setLatestAnswer(450000); + // await increaseTime(4 * 3600); + // let tx = await allMarkets.createMarket(0, 0, { gasPrice: 450000, from: user14 }); + // marketId++; + + // await plotusToken.transfer(user7, toWei(10000)); + // await plotusToken.approve(allMarkets.address, toWei(10000000), { from: user7 }); + // await allMarkets.deposit(toWei(100), { from: user7, value: toWei(0.1) }); + + // await allMarkets.placePrediction(marketId, ethAddress, to8Power(0.1), 3, { + // from: user7, + // }); + // await allMarkets.placePrediction(marketId, plotusToken.address, to8Power(100), 3, { + // from: user7, + // }); + // let rewardPoolEth = 0.1; + // let rewardPoolPlot = 99.95; + // let events = await marketIncentives.getPastEvents("allEvents", { fromBlock: 0, toBlock: "latest" }); + // eventData = findByTxHash(events, tx.tx); + // let gasUsed = eventData.gasUsed; + // let maxGas = 100 * 10 ** 9; + // let gasPrice = Math.min(maxGas, 450000 * 1.25, 450000); + // 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(8 * 60 * 60); + // await allMarkets.postResultMock(1, marketId); + // await increaseTime(8 * 60 * 60); + // let oldBalance = parseFloat(await plotusToken.balanceOf(user14)); + // let oldBalanceEth = parseFloat(await web3.eth.getBalance(user14)); + // tx = await marketIncentives.claimCreationReward(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 reward pool share of market", async function() { + marketId++; + await increaseTime(86400*30); + await plotusToken.transfer(user10, toWei(210000)); + await plotusToken.transfer(marketIncentives.address, toWei(100)); + await plotusToken.approve(tokenController.address, toWei(10000000), { from: user10 }); + await plotusToken.approve(allMarkets.address, toWei(10000000), { from: user10 }); + await tokenController.lock("0x534d", toWei(25000), 86400 * 30, { from: user10 }); + await increaseTime(4 * 3600); + let tx = await allMarkets.createMarket(0, 0, { from: user10 }); + + await plotusToken.transfer(user7, toWei(1000)); + await plotusToken.transfer(user7, toWei(5000)); + await plotusToken.approve(allMarkets.address, toWei(10000000), { from: user7 }); + + + await marketConfig.setNextOptionPrice(10); + await allMarkets.depositAndPlacePrediction(toWei(100), marketId, plotusToken.address, to8Power(100), 3, { from: user7 }); + await allMarkets.depositAndPlacePrediction(toWei(400), marketId, plotusToken.address, to8Power(400), 1, { from: user7 }); + // await allMarkets.depositAndPlacePrediction(toWei(100), marketId, plotusToken.address, to8Power(100), 1, { from: user7 }); + + let rewardPoolPlot = 99.95 + 66.66666666; + let events = await marketIncentives.getPastEvents("allEvents", { fromBlock: 0, toBlock: "latest" }); + eventData = findByTxHash(events, tx.tx); + let rewardPoolSharePerc = eventData.rewardPoolSharePerc; + assert.equal(rewardPoolSharePerc / 1, 100); + + await increaseTime(8 * 60 * 60); + await allMarkets.postResultMock(1, marketId); + let p1 = await governance.getProposalLength(); + await allMarkets.raiseDispute(marketId, String(1400000000000), "raise dispute", "this is description", "this is solution hash", { + from: user7 + }); + await increaseTime(604800); + await governance.closeProposal(p1); + await increaseTime(10000); + + await increaseTime(9 * 60 * 60); + + let oldBalance = parseFloat(await plotusToken.balanceOf(user10)); + tx = await marketIncentives.claimCreationReward(100, { from: user10 }); + let newBalance = parseFloat(await plotusToken.balanceOf(user10)); + assert.equal( + (newBalance / 1e18).toFixed(2), + (oldBalance / 1e18 + (rewardPoolPlot * rewardPoolSharePerc) / 10000).toFixed(2) + ); + }); + + it("Raise Dispute and pass: Scenario 2: Should be able to get reward pool share of market", async function() { + marketId++; + await increaseTime(86400*30); + await plotusToken.transfer(user10, toWei(25000)); + await plotusToken.approve(tokenController.address, toWei(10000000), { from: user10 }); + await plotusToken.approve(allMarkets.address, toWei(10000000), { from: user10 }); + await tokenController.extendLock("0x534d", 86400 * 30, { from: user10 }); + await increaseTime(4 * 3600); + let tx = await allMarkets.createMarket(0, 0, { from: user10 }); + + await plotusToken.transfer(user7, toWei(1000)); + await plotusToken.approve(allMarkets.address, toWei(10000000), { from: user7 }); + + + await marketConfig.setNextOptionPrice(10); + await allMarkets.depositAndPlacePrediction(toWei(100), marketId, plotusToken.address, to8Power(100), 3, { from: user7 }); + await allMarkets.depositAndPlacePrediction(toWei(400), marketId, plotusToken.address, to8Power(400), 1, { from: user7 }); + // await allMarkets.depositAndPlacePrediction(toWei(100), marketId, plotusToken.address, to8Power(100), 1, { from: user7 }); + + let rewardPoolPlot = 399.8 + 66.66666666; + let events = await marketIncentives.getPastEvents("allEvents", { fromBlock: 0, toBlock: "latest" }); + eventData = findByTxHash(events, tx.tx); + let rewardPoolSharePerc = eventData.rewardPoolSharePerc; + assert.equal(rewardPoolSharePerc / 1, 100); + + await increaseTime(8 * 60 * 60); + await allMarkets.postResultMock(1, marketId); + + let proposalId = await governance.getProposalLength(); + await allMarkets.raiseDispute(marketId, String(1400000000000), "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); + + await increaseTime(9 * 60 * 60); + + let oldBalance = parseFloat(await plotusToken.balanceOf(user10)); + tx = await marketIncentives.claimCreationReward(100, { from: user10 }); + let newBalance = parseFloat(await plotusToken.balanceOf(user10)); + assert.equal( + (newBalance / 1e18).toFixed(2), + (oldBalance / 1e18 + (rewardPoolPlot * 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() { + // //governance code + // let nullAddress = "0x0000000000000000000000000000"; + // let pc = await masterInstance.getLatestAddress(web3.utils.toHex("PC")); + // pc = await ProposalCategory.at(pc); + // let newGV = await GovernanceNew.new(); + // actionHash = encode1(["bytes2[]", "address[]"], [[toHex("GV")], [newGV.address]]); + + // let p = await governance.getProposalLength(); + // await governance.createProposal("proposal", "proposal", "proposal", 0); + // let canClose = await governance.canCloseProposal(p); + // assert.equal(parseFloat(canClose), 0); + // await governance.categorizeProposal(p, 7, 0); + // await governance.submitProposalWithSolution(p, "proposal", actionHash); + // await governance.submitVote(p, 1); + // await increaseTime(604800); + // await governance.closeProposal(p); + // await increaseTime(604800); + // await governance.triggerAction(p); + // await assertRevert(governance.triggerAction(p)); + // await increaseTime(604800); + + // let c1 = await pc.totalCategories(); + // //proposal to add category + // actionHash = encode1( + // ["uint256", "string", "uint256", "uint256", "uint256", "uint256[]", "uint256", "string", "address", "bytes2", "uint256[]", "string"], + // [ + // 10, + // "ResolveDispute", + // 3, + // 50, + // 50, + // [2], + // 86400, + // "QmZQhJunZesYuCJkdGwejSATTR8eynUgV8372cHvnAPMaM", + // nullAddress, + // toHex("AM"), + // [0, 0], + // "resolveDispute(uint256,uint256)", + // ] + // ); + // let p1 = await governance.getProposalLength(); + // await governance.createProposalwithSolution("Add new member", "Add new member", "Addnewmember", 4, "Add new member", actionHash); + // await governance.submitVote(p1.toNumber(), 1); + // await governance.closeProposal(p1.toNumber()); + // let cat2 = await pc.totalCategories(); + // await increaseTime(604800); + // governance = await GovernanceNew.at(governance.address); + // await governance.setAllMarketsAddress(); + // // governance code end + + // await plotusToken.transfer(user10, toWei(250000)); + // await plotusToken.approve(tokenController.address, toWei(10000000), { from: user10 }); + // await tokenController.lock("0x534d", toWei(25000), 86400 * 30, { from: user10 }); + + // await chainlinkGasAgg.setLatestAnswer(450000); + // let tx = await allMarkets.createMarket(0, 0, { gasPrice: 450000, from: user10 }); + // marketId++; + + // await plotusToken.transfer(user7, toWei(10000)); + // await plotusToken.approve(allMarkets.address, toWei(10000000), { from: user7 }); + // await allMarkets.deposit(toWei(100), { from: user7 }); + // await allMarkets.deposit(0, { from: user12, value: toWei(1.1) }); + + // await allMarkets.placePrediction(marketId, ethAddress, to8Power(0.1), 3, { + // from: user12, + // }); + // await allMarkets.placePrediction(marketId, ethAddress, to8Power(1), 1, { + // from: user12, + // }); + // await allMarkets.placePrediction(marketId, plotusToken.address, to8Power(100), 3, { + // from: user7, + // }); + + // let rewardPoolEth = 0.1; + // let rewardPoolPlot = 99.95; + // let events = await marketIncentives.getPastEvents("allEvents", { fromBlock: 0, toBlock: "latest" }); + // eventData = findByTxHash(events, tx.tx); + // let gasUsed = eventData.gasUsed; + // let maxGas = 100 * 10 ** 9; + // let gasPrice = Math.min(maxGas, 450000 * 1.25, 450000); + // 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(8 * 60 * 60); + // await allMarkets.postResultMock(1, marketId); + + // await plotusToken.transfer(user10, toWei(10000)); + // await plotusToken.approve(allMarkets.address, toWei(10000000), { from: user10 }); + // p1 = await governance.getProposalLength(); + + // await allMarkets.raiseDispute(marketId, String(1400000000000), "raise dispute", "this is description", "this is solution hash", { + // from: user10, + // }); + // await increaseTime(604800); + // await governance.closeProposal(p1); + // await increaseTime(10000); + // let oldBalance = parseFloat(await plotusToken.balanceOf(user10)); + // let oldBalanceEth = parseFloat(await web3.eth.getBalance(user10)); + // tx = await marketIncentives.claimCreationReward(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, toWei(10000000), { from: user10 }); + // await tokenController.extendLock("0x534d", 86400 * 30, { from: user10 }); + // await chainlinkGasAgg.setLatestAnswer(450000); + // await increaseTime(3610); + + // let tx = await allMarkets.createMarket(0, 0, { gasPrice: 450000, from: user10 }); + // marketId++; + // await plotusToken.transfer(user7, toWei(1000)); + // await plotusToken.approve(allMarkets.address, toWei(10000000), { from: user7 }); + // await allMarkets.deposit(0, { from: user12, value: toWei(1.1) }); + // await allMarkets.deposit(toWei(200), { from: user7 }); + + // await allMarkets.placePrediction(marketId, ethAddress, to8Power(0.1), 3, { from: user12 }); + // await allMarkets.placePrediction(marketId, ethAddress, to8Power(1), 1, { from: user12 }); + // await allMarkets.placePrediction(marketId, plotusToken.address, to8Power(100), 3, { from: user7 }); + // await allMarkets.placePrediction(marketId, plotusToken.address, to8Power(100), 1, { from: user7 }); + + // await increaseTime(8 * 60 * 60); + // await allMarkets.postResultMock(1, marketId); + + // let proposalId = await governance.getProposalLength(); + // await allMarkets.raiseDispute(marketId, "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); + // pendingRewards = await marketIncentives.getPendingMarketCreationRewards(user10, { from: user10 }); + // await governance.closeProposal(proposalId); + // await increaseTime(10000); + + // let rewardPoolEth = 0.99; + // let rewardPoolPlot = 99.95; + // let events = await marketIncentives.getPastEvents("allEvents", { fromBlock: 0, toBlock: "latest" }); + // eventData = findByTxHash(events, tx.tx); + // let gasUsed = eventData.gasUsed; + // let maxGas = 100 * 10 ** 9; + // let gasPrice = Math.min(maxGas, 450000 * 1.25, 450000); + // 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)); + // pendingRewards = await marketIncentives.getPendingMarketCreationRewards(user10, { from: user10 }); + // tx = await marketIncentives.claimCreationReward(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)); + // }); + + 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(8 * 60 * 60); + // let tx = await allMarkets.createMarket(0, 0, { gasPrice: 450000, from: user2 }); + // marketId++; + // market1 = marketId; + // await marketIncentives.claimCreationReward(5, { from: user2 }); + + // await plotusToken.transfer(user7, toWei(1000)); + // await plotusToken.approve(allMarkets.address, toWei(10000000), { from: user7 }); + // await allMarkets.deposit(0, { from: user7, value: toWei(1.1) }); + // await allMarkets.deposit(toWei(100), { from: user7 }); + + // await allMarkets.placePrediction(marketId, ethAddress, to8Power(0.1), 3, { from: user7 }); + // await allMarkets.placePrediction(marketId, ethAddress, to8Power(1), 1, { from: user7 }); + // await allMarkets.placePrediction(marketId, plotusToken.address, to8Power(100), 3, { from: user7 }); + // let rewardPoolEth = 0.1; + // let rewardPoolPlot = 99.95; + // let events = await marketIncentives.getPastEvents("allEvents", { fromBlock: 0, toBlock: "latest" }); + // eventData = findByTxHash(events, tx.tx); + // let gasUsed = eventData.gasUsed; + // let maxGas = 100 * 10 ** 9; + // let gasPrice = Math.min(maxGas, 450000 * 1.25, 450000); + // 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 allMarkets.createMarket(1, 0, { gasPrice: 450000, from: user2 }); + // marketId++; + // market2 = marketId; + // await marketIncentives.claimCreationReward(5, { from: user2 }); + + // await plotusToken.transfer(user7, toWei(1000)); + // await plotusToken.transfer(user12, toWei(1000)); + // await plotusToken.approve(allMarkets.address, toWei(10000000), { from: user7 }); + // await plotusToken.approve(allMarkets.address, toWei(10000000), { from: user12 }); + // await allMarkets.deposit(toWei(100), { from: user7, value: toWei(0.1) }); + // await allMarkets.deposit(toWei(100), { from: user12, value: toWei(1) }); + + // await allMarkets.placePrediction(marketId, ethAddress, to8Power(0.1), 3, { from: user12 }); + // await allMarkets.placePrediction(marketId, ethAddress, to8Power(1), 1, { from: user7 }); + // await allMarkets.placePrediction(marketId, plotusToken.address, to8Power(100), 3, { from: user12 }); + // await allMarkets.placePrediction(marketId, plotusToken.address, to8Power(100), 1, { from: user7 }); + // let rewardPoolEth = 0.999; + // let rewardPoolPlot = 99.95; + // let events = await marketIncentives.getPastEvents("allEvents", { fromBlock: 0, toBlock: "latest" }); + // eventData = findByTxHash(events, tx.tx); + // let gasUsed = eventData.gasUsed; + // let maxGas = 100 * 10 ** 9; + // let gasPrice = Math.min(maxGas, 450000 * 1.25, 450000); + // 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 allMarkets.createMarket(0, 1, { gasPrice: 450000, from: user2 }); + // marketId++; + // market3 = marketId; + // await marketIncentives.claimCreationReward(5, { from: user2 }); + + // await plotusToken.transfer(user7, toWei(1000)); + // await plotusToken.approve(allMarkets.address, toWei(10000000), { from: user7 }); + // await allMarkets.deposit(toWei(100), { from: user7, value: toWei(0.1) }); + + // await allMarkets.placePrediction(marketId, ethAddress, to8Power(0.1), 3, { + // from: user7, + // }); + // await allMarkets.placePrediction(marketId, ethAddress, to8Power(1), 1, { + // from: user7, + // }); + // await allMarkets.placePrediction(marketId, plotusToken.address, to8Power(100), 3, { + // from: user7, + // }); + // let rewardPoolEth = 0.1; + // let rewardPoolPlot = 99.95; + // let events = await marketIncentives.getPastEvents("allEvents", { fromBlock: 0, toBlock: "latest" }); + // eventData = findByTxHash(events, tx.tx); + // let gasUsed = eventData.gasUsed; + // let maxGas = 100 * 10 ** 9; + // let gasPrice = Math.min(maxGas, 450000 * 1.25, 450000); + // 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(marketIncentives.claimCreationReward(100, { from: user2 })); + // await increaseTime(8 * 60 * 60); + // await allMarkets.postResultMock(1, market1); + // await allMarkets.postResultMock(1, market2); + // let proposalId = await governance.getProposalLength(); + // await allMarkets.raiseDispute(market2, "1690897978359414786", "raise dispute", "this is description", "this is solution hash", { from: user10 }); + // }); + // it("Should be able to claim market 1 rewards", async function() { + // await increaseTime(2 * 60 * 60); + // let oldBalance = parseFloat(await plotusToken.balanceOf(user2)); + // let oldBalanceEth = parseFloat(await web3.eth.getBalance(user2)); + // tx = await marketIncentives.claimCreationReward(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(marketIncentives.claimCreationReward(100, { from: user2 })); + // }); + // it("Create Market 4", async function() { + // await chainlinkGasAgg.setLatestAnswer(450000); + // let tx = await allMarkets.createMarket(0, 0, { gasPrice: 450000, from: user2 }); + // await marketIncentives.claimCreationReward(5, { from: user2 }); + // marketId++; + // market4 = marketId; + + // await plotusToken.transfer(user7, toWei(1000)); + // await plotusToken.approve(allMarkets.address, toWei(10000000), { from: user7 }); + // await allMarkets.deposit(toWei(100), { from: user7, value: toWei(1.1) }); + + // await allMarkets.placePrediction(marketId, ethAddress, to8Power(0.1), 3, { from: user7 }); + // await allMarkets.placePrediction(marketId, ethAddress, to8Power(1), 1, { from: user7 }); + // await allMarkets.placePrediction(marketId, plotusToken.address, to8Power(100), 3, { from: user7 }); + // let rewardPoolEth = 0.1; + // let rewardPoolPlot = 99.95; + // let events = await marketIncentives.getPastEvents("allEvents", { fromBlock: 0, toBlock: "latest" }); + // eventData = findByTxHash(events, tx.tx); + // let gasUsed = eventData.gasUsed; + // let maxGas = 100 * 10 ** 9; + // let gasPrice = Math.min(maxGas, 450000 * 1.25, 450000); + // 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(8*60*60); + // await allMarkets.postResultMock(1, market4); + // await increaseTime(2*60*60); + // let oldBalance = parseFloat(await plotusToken.balanceOf(user2)); + // let oldBalanceEth = parseFloat(await web3.eth.getBalance(user2)); + // tx = await marketIncentives.claimCreationReward(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(marketIncentives.claimCreationReward(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 marketIncentives.claimCreationReward(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 participation rewards", async function() { + // let reward = await allMarkets.getReturn(user7, market2); + // reward = await allMarkets.getReturn(user12, market2); + // await allMarkets.withdrawMax(100, { from: user7 }); + // let perc = await marketIncentives.getMarketCreatorRPoolShareParams(market2 , 0, 0); + // assert.equal(reward[0][0] / 1e8, 99.95 + 99.95 - (perc[0] * 1 * 99.95) / 10000); + // }); + + // it("Should be able to claim market 3 rewards", async function() { + // await increaseTime(2*24*60*60); + // await allMarkets.postResultMock(1, market3); + // await increaseTime(2*24*60*60); + // let oldBalance = parseFloat(await plotusToken.balanceOf(user2)); + // let oldBalanceEth = parseFloat(await web3.eth.getBalance(user2)); + // tx = await marketIncentives.claimCreationReward(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(marketIncentives.claimCreationReward(100, { from: user2 })); + // }); + + // it("Should Add category to pause market creation of particular type of market", async function() { // await increaseTime(604800); // 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")); // 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 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"); // }); // 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"); // }); // 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"); // }); +}); diff --git a/test/25_sponsorIncentives.test.js b/test/25_sponsorIncentives.test.js new file mode 100644 index 000000000..f8c02c6b8 --- /dev/null +++ b/test/25_sponsorIncentives.test.js @@ -0,0 +1,294 @@ +const { assert } = require("chai"); +const OwnedUpgradeabilityProxy = artifacts.require("OwnedUpgradeabilityProxy"); +const Market = artifacts.require("MockMarket"); +const Plotus = artifacts.require("MarketRegistry"); +const Master = artifacts.require("Master"); +const MemberRoles = artifacts.require("MemberRoles"); +const PlotusToken = artifacts.require("MockPLOT"); +const MockWeth = artifacts.require("MockWeth"); +const MockConfig = artifacts.require("MockConfig"); //mock +const Governance = artifacts.require("GovernanceV2"); +const AllMarkets = artifacts.require("MockAllMarkets"); +const MockUniswapRouter = artifacts.require("MockUniswapRouter"); +const MockUniswapV2Pair = artifacts.require("MockUniswapV2Pair"); +const MockUniswapFactory = artifacts.require("MockUniswapFactory"); +const TokenController = artifacts.require("MockTokenController"); +const DummyTokenMock2 = artifacts.require("SampleERC"); + +const web3 = Market.web3; +const ethAddress = "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE"; +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 gvProposal = require("./utils/gvProposal.js").gvProposalWithIncentiveViaTokenHolder; +const { toHex, toWei, toChecksumAddress } = require("./utils/ethTools"); +const to8Power = (number) => String(parseFloat(number) * 1e8); + +// Multiplier Sheet + +contract("25_sponsorIncentive. AllMarket", async function([ + ab1, + ab2, + ab3, + ab4, + mem1, + mem2, + mem3, + mem4, + mem5, + mem6, + mem7, + mem8, + mem9, + mem10, + notMember, + dr1, + dr2, + dr3, + user11, + user12, + user13, +]) { + let masterInstance, + plotusToken, + mockMarketConfig, + MockUniswapRouterInstance, + tokenControllerAdd, + tokenController, + plotusNewAddress, + plotusNewInstance, + governance, + mockUniswapV2Pair, + mockUniswapFactory, + weth, + allMarkets, + dToken; + before(async () => { + dToken = await DummyTokenMock2.new("Dummy", "DYM"); + await dToken.mint(toWei(10000)); + 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")); + let 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); + mockMarketConfig = await plotusNewInstance.marketUtility(); + mockMarketConfig = await MockConfig.at(mockMarketConfig); + weth = await MockWeth.deployed(); + await mockMarketConfig.setWeth(weth.address); + let newUtility = await MockConfig.new(); + let actionHash = encode( + "upgradeContractImplementation(address,address)", + mockMarketConfig.address, + newUtility.address + ); + await gvProposal( + 6, + actionHash, + await MemberRoles.at(await masterInstance.getLatestAddress(toHex("MR"))), + governance, + 2, + 0 + ); + await increaseTime(604800); + mockUniswapV2Pair = await MockUniswapV2Pair.new(); + await mockUniswapV2Pair.initialize(plotusToken.address, weth.address); + await weth.deposit({ from: user11, value: toWei(10) }); + await weth.transfer(mockUniswapV2Pair.address, toWei(10), { from: user11 }); + await plotusToken.transfer(mockUniswapV2Pair.address, toWei(1000)); + initialPLOTPrice = 1000 / 10; + initialEthPrice = 10 / 1000; + await mockUniswapFactory.setPair(mockUniswapV2Pair.address); + await mockUniswapV2Pair.sync(); + newUtility = await MockConfig.new(); + actionHash = encode( + "upgradeContractImplementation(address,address)", + mockMarketConfig.address, + newUtility.address + ); + await gvProposal( + 6, + actionHash, + await MemberRoles.at(await masterInstance.getLatestAddress(toHex("MR"))), + governance, + 2, + 0 + ); + await increaseTime(604800); + allMarkets = await AllMarkets.at(await masterInstance.getLatestAddress(web3.utils.toHex("AM"))); + let date = await latestTime(); + await increaseTime(3610); + date = Math.round(date); + await mockMarketConfig.setInitialCummulativePrice(); + await mockMarketConfig.setAuthorizedAddress(allMarkets.address); + let utility = await MockConfig.at("0xCBc7df3b8C870C5CDE675AaF5Fd823E4209546D2"); + await utility.setAuthorizedAddress(allMarkets.address); + await mockUniswapV2Pair.sync(); + }); + + it("25.1 Whitelist sponsor", async () => { + await plotusToken.transfer(mem1, toWei(100)); + await plotusToken.transfer(mem2, toWei(100)); + await plotusToken.transfer(mem3, toWei(100)); + await plotusToken.transfer(mem4, toWei(100)); + await plotusToken.transfer(mem5, toWei(100)); + await increaseTime(604810); + pId = (await governance.getProposalLength()).toNumber(); + await governance.createProposal("Proposal2", "Proposal2", "Proposal2", 0); //Pid 3 + await governance.categorizeProposal(pId, 23, 0); + let actionHash = encode("whitelistSponsor(address)", ab1); + await governance.submitProposalWithSolution(pId, "whitelistSponsor", actionHash); + await governance.submitVote(pId, 1, { from: ab1 }); + await governance.submitVote(pId, 1, { from: mem1 }); + await governance.submitVote(pId, 1, { from: mem2 }); + await governance.submitVote(pId, 1, { from: mem3 }); + await governance.submitVote(pId, 1, { from: mem4 }); + await governance.submitVote(pId, 1, { from: mem5 }); + let canClose = await governance.canCloseProposal(pId); + assert.equal(canClose.toNumber(), 0); + await increaseTime(604810); + await assertRevert(governance.submitVote(pId, 1, { from: mem2 })); //closed to vote + await governance.closeProposal(pId); + await increaseTime(604850); + await governance.triggerAction(pId); + let actionStatus = await governance.proposalActionStatus(pId); + assert.equal(actionStatus / 1, 3); + }); + it("25.2 Create Market and add sponsorIncentives", async () => { + await plotusToken.approve(allMarkets.address, toWei("1000000000"), { from: ab1 }); + await dToken.approve(allMarkets.address, toWei("1000000000"), { from: ab1 }); + + await allMarkets.createMarket(0, 0); //7 eth 4hr + await allMarkets.sponsorIncentives(7, plotusToken.address, toWei(1)); + await allMarkets.createMarket(0, 1); //8 eth daily + await allMarkets.sponsorIncentives(8, plotusToken.address, toWei(1)); + await allMarkets.createMarket(1, 0); //9 btc 4hr + await allMarkets.sponsorIncentives(9, dToken.address, toWei(1)); + await allMarkets.createMarket(1, 1); //9 btc daily + await allMarkets.sponsorIncentives(10, dToken.address, toWei(1)); + }); + it("25.3 Place predictions", async () => { + await MockUniswapRouterInstance.setPrice("1000000000000000"); + await mockMarketConfig.setPrice("1000000000000000"); + await mockMarketConfig.setNextOptionPrice(9); + + await allMarkets.deposit(0, { from: user11, value: toWei(4) }); + await allMarkets.deposit(0, { from: user12, value: toWei(2) }); + await allMarkets.placePrediction(7, ethAddress, to8Power("1"), 1, { from: user11 }); + await allMarkets.placePrediction(7, ethAddress, to8Power("0.5"), 1, { from: user12 }); + await allMarkets.placePrediction(8, ethAddress, to8Power("1"), 1, { from: user11 }); + await allMarkets.placePrediction(8, ethAddress, to8Power("0.5"), 1, { from: user12 }); + await allMarkets.placePrediction(9, ethAddress, to8Power("1"), 1, { from: user11 }); + await allMarkets.placePrediction(9, ethAddress, to8Power("0.5"), 1, { from: user12 }); + await allMarkets.placePrediction(10, ethAddress, to8Power("1"), 1, { from: user11 }); + await allMarkets.placePrediction(10, ethAddress, to8Power("0.5"), 1, { from: user12 }); + }); + it("25.4 Claim sponsorship rewards", async () => { + await increaseTime(8 * 60 * 60); + await allMarkets.postResultMock(1, 7); + await allMarkets.postResultMock(1, 9); + await increaseTime(8 * 60 * 60); + + //user11, user12 claim market 7 sp rewards in plot + const user11PPInPLOT = (await allMarkets.getUserPredictionPoints(user11, 7, 1)) / 1e5; //same for all markets as the prediction amount is same + const user12PPInPLOT = (await allMarkets.getUserPredictionPoints(user12, 7, 1)) / 1e5; //same for all markets as the prediction amount is same + let ratio = user11PPInPLOT / user12PPInPLOT; //same for all markets as the prediction amount is same + + let plotBalanceBeforeUser11 = (await plotusToken.balanceOf(user11)) / 1e18; + let plotBalanceBeforeUser12 = (await plotusToken.balanceOf(user12)) / 1e18; + let dummyBalanceBeforeUser11 = (await dToken.balanceOf(user11)) / 1e18; + let dummyBalanceBeforeUser12 = (await dToken.balanceOf(user12)) / 1e18; + + await allMarkets.claimIncentives(user11, [7], plotusToken.address); + await allMarkets.claimIncentives(user12, [7], plotusToken.address); + + let plotBalanceAfterUser11 = (await plotusToken.balanceOf(user11)) / 1e18; + let plotBalanceAfterUser12 = (await plotusToken.balanceOf(user12)) / 1e18; + let dummyBalanceAfterUser11 = (await dToken.balanceOf(user11)) / 1e18; + let dummyBalanceAfterUser12 = (await dToken.balanceOf(user12)) / 1e18; + + await assertRevert(allMarkets.claimIncentives(user12, [7, 8, 9, 10], plotusToken.address)); + await assertRevert(allMarkets.claimIncentives(user11, [7, 8, 9, 10], plotusToken.address)); + assert.equal((plotBalanceAfterUser11 - plotBalanceBeforeUser11).toFixed(5), ((1 / 3) * ratio).toFixed(5)); + assert.equal((plotBalanceAfterUser12 - plotBalanceBeforeUser12).toFixed(5), (1 / 3).toFixed(5)); + assert.equal(dummyBalanceAfterUser11 - dummyBalanceBeforeUser11, 0); + assert.equal(dummyBalanceAfterUser12 - dummyBalanceBeforeUser12, 0); + + //user11, user12 claim market 9 sp rewards in dToken + plotBalanceBeforeUser11 = (await plotusToken.balanceOf(user11)) / 1e18; + plotBalanceBeforeUser12 = (await plotusToken.balanceOf(user12)) / 1e18; + dummyBalanceBeforeUser11 = (await dToken.balanceOf(user11)) / 1e18; + dummyBalanceBeforeUser12 = (await dToken.balanceOf(user12)) / 1e18; + + await allMarkets.claimIncentives(user11, [9], dToken.address); + await allMarkets.claimIncentives(user12, [9], dToken.address); + + plotBalanceAfterUser11 = (await plotusToken.balanceOf(user11)) / 1e18; + plotBalanceAfterUser12 = (await plotusToken.balanceOf(user12)) / 1e18; + dummyBalanceAfterUser11 = (await dToken.balanceOf(user11)) / 1e18; + dummyBalanceAfterUser12 = (await dToken.balanceOf(user12)) / 1e18; + + await assertRevert(allMarkets.claimIncentives(user11, [7, 8, 9, 10], dToken.address)); + await assertRevert(allMarkets.claimIncentives(user12, [7, 8, 9, 10], dToken.address)); + assert.equal(plotBalanceAfterUser11 - plotBalanceBeforeUser11, 0); + assert.equal(plotBalanceAfterUser12 - plotBalanceBeforeUser12, 0); + assert.equal((dummyBalanceAfterUser11 - dummyBalanceBeforeUser11).toFixed(5), ((1 / 3) * ratio).toFixed(5)); + assert.equal((dummyBalanceAfterUser12 - dummyBalanceBeforeUser12).toFixed(5), (1 / 3).toFixed(5)); + + //For markets 8,10 + await increaseTime(24 * 2 * 60 * 60); + await allMarkets.postResultMock(1, 8); + await allMarkets.postResultMock(1, 10); + await increaseTime(24 * 2 * 60 * 60); + + //user11, user12 claim market 7 sp rewards in plot + plotBalanceBeforeUser11 = (await plotusToken.balanceOf(user11)) / 1e18; + plotBalanceBeforeUser12 = (await plotusToken.balanceOf(user12)) / 1e18; + dummyBalanceBeforeUser11 = (await dToken.balanceOf(user11)) / 1e18; + dummyBalanceBeforeUser12 = (await dToken.balanceOf(user12)) / 1e18; + + await allMarkets.claimIncentives(user11, [8], plotusToken.address); + await allMarkets.claimIncentives(user12, [8], plotusToken.address); + + plotBalanceAfterUser11 = (await plotusToken.balanceOf(user11)) / 1e18; + plotBalanceAfterUser12 = (await plotusToken.balanceOf(user12)) / 1e18; + dummyBalanceAfterUser11 = (await dToken.balanceOf(user11)) / 1e18; + dummyBalanceAfterUser12 = (await dToken.balanceOf(user12)) / 1e18; + + await assertRevert(allMarkets.claimIncentives(user12, [7, 8, 9, 10], plotusToken.address)); + await assertRevert(allMarkets.claimIncentives(user11, [7, 8, 9, 10], plotusToken.address)); + assert.equal((plotBalanceAfterUser11 - plotBalanceBeforeUser11).toFixed(5), ((1 / 3) * ratio).toFixed(5)); + assert.equal((plotBalanceAfterUser12 - plotBalanceBeforeUser12).toFixed(5), (1 / 3).toFixed(5)); + assert.equal(dummyBalanceAfterUser11 - dummyBalanceBeforeUser11, 0); + assert.equal(dummyBalanceAfterUser12 - dummyBalanceBeforeUser12, 0); + + //user11, user12 claim market 9 sp rewards in dToken + plotBalanceBeforeUser11 = (await plotusToken.balanceOf(user11)) / 1e18; + plotBalanceBeforeUser12 = (await plotusToken.balanceOf(user12)) / 1e18; + dummyBalanceBeforeUser11 = (await dToken.balanceOf(user11)) / 1e18; + dummyBalanceBeforeUser12 = (await dToken.balanceOf(user12)) / 1e18; + + await allMarkets.claimIncentives(user11, [10], dToken.address); + await allMarkets.claimIncentives(user12, [10], dToken.address); + + plotBalanceAfterUser11 = (await plotusToken.balanceOf(user11)) / 1e18; + plotBalanceAfterUser12 = (await plotusToken.balanceOf(user12)) / 1e18; + dummyBalanceAfterUser11 = (await dToken.balanceOf(user11)) / 1e18; + dummyBalanceAfterUser12 = (await dToken.balanceOf(user12)) / 1e18; + + await assertRevert(allMarkets.claimIncentives(user11, [7, 8, 9, 10], dToken.address)); + await assertRevert(allMarkets.claimIncentives(user12, [7, 8, 9, 10], dToken.address)); + assert.equal(plotBalanceAfterUser11 - plotBalanceBeforeUser11, 0); + assert.equal(plotBalanceAfterUser12 - plotBalanceBeforeUser12, 0); + assert.equal((dummyBalanceAfterUser11 - dummyBalanceBeforeUser11).toFixed(5), ((1 / 3) * ratio).toFixed(5)); + assert.equal((dummyBalanceAfterUser12 - dummyBalanceBeforeUser12).toFixed(5), (1 / 3).toFixed(5)); + }); +}); diff --git a/test/MetaTxTestcase.test.js b/test/MetaTxTestcase.test.js new file mode 100644 index 000000000..1d64f1302 --- /dev/null +++ b/test/MetaTxTestcase.test.js @@ -0,0 +1,238 @@ +const OwnedUpgradeabilityProxy = artifacts.require('OwnedUpgradeabilityProxy'); +const Governance = artifacts.require("Governance"); +const MemberRoles = artifacts.require("MockMemberRoles"); +const ProposalCategory = artifacts.require("ProposalCategory"); +const TokenController = artifacts.require("TokenController"); +const Master = artifacts.require("Master"); +const IERC1132 = artifacts.require("IERC1132"); +const PlotusToken = artifacts.require("MockPLOT"); +const assertRevert = require("./utils/assertRevert.js").assertRevert; +const increaseTime = require("./utils/increaseTime.js").increaseTime; +const latestTime = require("./utils/latestTime.js").latestTime; +const { toHex, toWei } = require("./utils/ethTools.js"); +const expectEvent = require("./utils/expectEvent"); +const Web3 = require("web3"); +const { assert } = require("chai"); +const web3 = new Web3(); +const encode = require("./utils/encoder.js").encode3; +const signAndExecuteMetaTx = require("./utils/signAndExecuteMetaTx.js").signAndExecuteMetaTx; +let maxAllowance = "115792089237316195423570985008687907853269984665640564039457584007913129639935"; +let privateKeyList = ["fb437e3e01939d9d4fef43138249f23dc1d0852e69b0b5d1647c087f869fabbd","7c85a1f1da3120c941b83d71a154199ee763307683f206b98ad92c3b4e0af13e","ecc9b35bf13bd5459350da564646d05c5664a7476fe5acdf1305440f88ed784c","f4470c3fca4dbef1b2488d016fae25978effc586a1f83cb29ac8cb6ab5bc2d50","141319b1a84827e1046e93741bf8a9a15a916d49684ab04925ac4ce4573eea23","d54b606094287758dcf19064a8d91c727346aadaa9388732e73c4315b7c606f9","49030e42ce4152e715a7ddaa10e592f8e61d00f70ef11f48546711f159d985df","b96761b1e7ebd1e8464a78a98fe52f53ce6035c32b4b2b12307a629a551ff7cf","d4786e2581571c863c7d12231c3afb6d4cef390c0ac9a24b243293721d28ea95","ed28e3d3530544f1cf2b43d1956b7bd13b63c612d963a8fb37387aa1a5e11460","05b127365cf115d4978a7997ee98f9b48f0ddc552b981c18aa2ee1b3e6df42c6","9d11dd6843f298b01b34bd7f7e4b1037489871531d14b58199b7cba1ac0841e6","f79e90fa4091de4fc2ec70f5bf67b24393285c112658e0d810e6bd711387fbb9","99f1fc0f09230ce745b6a256ba7082e6e51a2907abda3d9e735a5c8188bb4ba1","477f86cce983b9c91a36fdcd4a7ce21144a08dee9b1aafb91b9c70e57f717ce6","b03d2e6bb4a7d71c66a66ff9e9c93549cae4b593f634a4ea2a1f79f94200f5b4","9ddc0f53a81e631dcf39d5155f41ec12ed551b731efc3224f410667ba07b37dc","cf087ff9ae7c9954ad8612d071e5cdf34a6024ee1ae477217639e63a802a53dd","b64f62b94babb82cc78d3d1308631ae221552bb595202fc1d267e1c29ce7ba60","a91e24875f8a534497459e5ccb872c4438be3130d8d74b7e1104c5f94cdcf8c2","4f49f3d029eeeb3fed14d59625acd088b6b34f3b41c527afa09d29e4a7725c32","179795fd7ac7e7efcba3c36d539a1e8659fb40d77d0a3fab2c25562d99793086","4ba37d0b40b879eceaaca2802a1635f2e6d86d5c31e3ff2d2fd13e68dd2a6d3d","6b7f5dfba9cd3108f1410b56f6a84188eee23ab48a3621b209a67eea64293394","870c540da9fafde331a3316cee50c17ad76ddb9160b78b317bef2e6f6fc4bac0","470b4cccaea895d8a5820aed088357e380d66b8e7510f0a1ea9b575850160241","8a55f8942af0aec1e0df3ab328b974a7888ffd60ded48cc6862013da0f41afbc","2e51e8409f28baf93e665df2a9d646a1bf9ac8703cbf9a6766cfdefa249d5780","99ef1a23e95910287d39493d8d9d7d1f0b498286f2b1fdbc0b01495f10cf0958","6652200c53a4551efe2a7541072d817562812003f9d9ef0ec17995aa232378f8","39c6c01194df72dda97da2072335c38231ced9b39afa280452afcca901e73643","12097e411d948f77b7b6fa4656c6573481c1b4e2864c1fca9d5b296096707c45","cbe53bf1976aee6cec830a848c6ac132def1503cffde82ccfe5bd15e75cbaa72","eeab5dcfff92dbabb7e285445aba47bd5135a4a3502df59ac546847aeb5a964f","5ea8279a578027abefab9c17cef186cccf000306685e5f2ee78bdf62cae568dd","0607767d89ad9c7686dbb01b37248290b2fa7364b2bf37d86afd51b88756fe66","e4fd5f45c08b52dae40f4cdff45e8681e76b5af5761356c4caed4ca750dc65cd","145b1c82caa2a6d703108444a5cf03e9cb8c3cd3f19299582a564276dbbba734","736b22ec91ae9b4b2b15e8d8c220f6c152d4f2228f6d46c16e6a9b98b4733120","ac776cb8b40f92cdd307b16b83e18eeb1fbaa5b5d6bd992b3fda0b4d6de8524c","65ba30e2202fdf6f37da0f7cfe31dfb5308c9209885aaf4cef4d572fd14e2903","54e8389455ec2252de063e83d3ce72529d674e6d2dc2070661f01d4f76b63475","fbbbfb525dd0255ee332d51f59648265aaa20c2e9eff007765cf4d4a6940a849","8de5e418f34d04f6ea947ce31852092a24a705862e6b810ca9f83c2d5f9cda4d","ea6040989964f012fd3a92a3170891f5f155430b8bbfa4976cde8d11513b62d9","14d94547b5deca767137fbd14dae73e888f3516c742fad18b83be333b38f0b88","47f05203f6368d56158cda2e79167777fc9dcb0c671ef3aabc205a1636c26a29"]; + +let gv; +let cr; +let pc; +let nxms; +let proposalId; +let pId; +let mr; +let plotusToken; +let tc; +let td; + +contract("MetaTxs", ([user1,user2,user3,user4]) => { + before(async function () { + nxms = await OwnedUpgradeabilityProxy.deployed(); + nxms = await Master.at(nxms.address); + plotusToken = await PlotusToken.deployed(); + let address = await nxms.getLatestAddress(toHex("GV")); + gv = await Governance.at(address); + address = await nxms.getLatestAddress(toHex("PC")); + pc = await ProposalCategory.at(address); + address = await nxms.getLatestAddress(toHex("MR")); + mr = await MemberRoles.at(address); + tc = await TokenController.at(await nxms.getLatestAddress(toHex("TC"))); + await plotusToken.transfer(user2,toWei(3000)); + }); +describe('PlotxToken Test Cases', function() { + + it("Should be able to transfer plot via meta transaction", async function () { + let functionSignature = encode("transfer(address,uint256)", user3, toWei(1000)); + + let user1BalBefore = (await plotusToken.balanceOf(user2))/1e18; + let user2BalBefore = (await plotusToken.balanceOf(user3))/1e18; + await signAndExecuteMetaTx( + privateKeyList[1], + user2, + functionSignature, + plotusToken, + "PLOT" + ); + let user1BalAfter = (await plotusToken.balanceOf(user2))/1e18; + let user2BalAfter = (await plotusToken.balanceOf(user3))/1e18; + + assert.equal(user1BalAfter, user1BalBefore - 1000); + assert.equal(user2BalAfter, user2BalBefore/1 + 1000); + }); + + it("Should be able to approve plot via meta transaction", async function () { + let functionSignature = encode("approve(address,uint256)", user3, toWei(1234)); + + let approvalBefore = (await plotusToken.allowance(user2,user3))/1e18; + await signAndExecuteMetaTx( + privateKeyList[1], + user2, + functionSignature, + plotusToken, + "PLOT" + ); + let approvalAfter = (await plotusToken.allowance(user2,user3))/1e18; + + assert.equal(approvalAfter, approvalBefore/1 + 1234); + }); + + it("Should be able to increase plot allowance via meta transaction", async function () { + let functionSignature = encode("increaseAllowance(address,uint256)", user3, toWei(200)); + + let approvalBefore = (await plotusToken.allowance(user2,user3))/1e18; + await signAndExecuteMetaTx( + privateKeyList[1], + user2, + functionSignature, + plotusToken, + "PLOT" + ); + let approvalAfter = (await plotusToken.allowance(user2,user3))/1e18; + + assert.equal(approvalAfter, approvalBefore/1 + 200); + }); + + it("Should be able to decrease plot allowance via meta transaction", async function () { + let functionSignature = encode("decreaseAllowance(address,uint256)", user3, toWei(100)); + + let approvalBefore = (await plotusToken.allowance(user2,user3))/1e18; + await signAndExecuteMetaTx( + privateKeyList[1], + user2, + functionSignature, + plotusToken, + "PLOT" + ); + let approvalAfter = (await plotusToken.allowance(user2,user3))/1e18; + + assert.equal(approvalAfter, approvalBefore/1 - 100); + }); + + it("Should be able to spend plot after getting approval via meta transaction", async function () { + let functionSignature = encode("transferFrom(address,address,uint256)", user2,user4, toWei(500)); + + let user2BalBefore = (await plotusToken.balanceOf(user2))/1e18; + let user4BalBefore = (await plotusToken.balanceOf(user4))/1e18; + let approvalBefore = (await plotusToken.allowance(user2,user3))/1e18; + await signAndExecuteMetaTx( + privateKeyList[2], + user3, + functionSignature, + plotusToken, + "PLOT" + ); + let user2BalAfter = (await plotusToken.balanceOf(user2))/1e18; + let user4BalAfter = (await plotusToken.balanceOf(user4))/1e18; + let approvalAfter = (await plotusToken.allowance(user2,user3))/1e18; + + assert.equal(user2BalAfter, user2BalBefore - 500); + assert.equal(user4BalAfter, user4BalBefore/1 + 500); + assert.equal(approvalAfter, approvalBefore/1 - 500); + }); + + it("Should be able to call functions with onlyOperator via meta transaction", async function () { + + let newPlotTok = await PlotusToken.new("PLOT1", "PLOT1", 18, user1, user1); + + //lockForGovernanceVote + + functionSignature = encode("lockForGovernanceVote(address,uint256)", user3, 100000); + + + assert.equal(await newPlotTok.isLockedForGV(user3), false); + await signAndExecuteMetaTx( + privateKeyList[0], + user1, + functionSignature, + newPlotTok, + "PLOT1" + ); + + assert.equal(await newPlotTok.isLockedForGV(user3), true); + + //changeOperator + + functionSignature = encode("changeOperator(address)", user2); + + + assert.equal(await newPlotTok.operator(), user1); + await signAndExecuteMetaTx( + privateKeyList[0], + user1, + functionSignature, + newPlotTok, + "PLOT1" + ); + + assert.equal(await newPlotTok.operator(), user2); + + }); +}); + +describe('Token Controller Test Cases', function() { + + it("Should be able to Lock plot via meta transaction", async function () { + await plotusToken.transfer(user2, toWei(100)); + await plotusToken.approve(tc.address,toWei(100),{from:user2}); + let functionSignature = encode("lock(bytes32,uint256,uint256)", toHex("DR"), toWei(10), 10000); + + let user2BalBefore = (await plotusToken.balanceOf(user2))/1e18; + let user2LockedBefore = (await tc.tokensLocked(user2, toHex("DR")))/1e18; + await signAndExecuteMetaTx( + privateKeyList[1], + user2, + functionSignature, + tc, + "TC" + ); + let user2BalAfter = (await plotusToken.balanceOf(user2))/1e18; + let user2LockedAfter = (await tc.tokensLocked(user2,toHex("DR")))/1e18; + + assert.equal(user2BalAfter, user2BalBefore - 10); + assert.equal(user2LockedAfter, user2LockedBefore/1 + 10); + }); + + it("Should be able to increase lock amount plot via meta transaction", async function () { + let functionSignature = encode("increaseLockAmount(bytes32,uint256)", toHex("DR"), toWei(15)); + + let user2BalBefore = (await plotusToken.balanceOf(user2))/1e18; + let user2LockedBefore = (await tc.tokensLocked(user2, toHex("DR")))/1e18; + await signAndExecuteMetaTx( + privateKeyList[1], + user2, + functionSignature, + tc, + "TC" + ); + let user2BalAfter = (await plotusToken.balanceOf(user2))/1e18; + let user2LockedAfter = (await tc.tokensLocked(user2,toHex("DR")))/1e18; + + assert.equal(user2BalAfter, user2BalBefore - 15); + assert.equal(user2LockedAfter, user2LockedBefore/1 + 15); + }); + + it("Should be able to extend Lock validity plot via meta transaction", async function () { + let functionSignature = encode("extendLock(bytes32,uint256)", toHex("DR"), 1000); + + let lockableTok = await IERC1132.at(tc.address); + let lcokedBefore = (await lockableTok.locked(user2, toHex("DR"))); + await signAndExecuteMetaTx( + privateKeyList[1], + user2, + functionSignature, + tc, + "TC" + ); + let lcokedAfter = (await lockableTok.locked(user2, toHex("DR"))); + + assert.equal(lcokedAfter[1], lcokedBefore[1]/1 + 1000); + }); + +}); + +}); diff --git a/test/OUTDATED-02_AirdropBlot.test.js b/test/OUTDATED-02_AirdropBlot.test.js new file mode 100644 index 000000000..c51f1b6d5 --- /dev/null +++ b/test/OUTDATED-02_AirdropBlot.test.js @@ -0,0 +1,442 @@ +// const { assert } = require("chai"); + +// const OwnedUpgradeabilityProxy = artifacts.require("OwnedUpgradeabilityProxy"); +// const Market = artifacts.require("MockMarket"); +// const Plotus = artifacts.require("MarketRegistry"); +// const Master = artifacts.require("Master"); +// const Airdrop = artifacts.require("Airdrop"); +// const MarketConfig = artifacts.require("MockConfig"); +// const PlotusToken = artifacts.require("MockPLOT"); +// const TokenController = artifacts.require("TokenController"); +// const BLOT = artifacts.require("BLOT"); +// const MockUniswapRouter = artifacts.require("MockUniswapRouter"); +// const BigNumber = require("bignumber.js"); + +// const web3 = Market.web3; +// const increaseTime = require("./utils/increaseTime.js").increaseTime; +// const assertRevert = require("./utils/assertRevert.js").assertRevert; +// const latestTime = require("./utils/latestTime.js").latestTime; +// const { toHex, toWei } = require("./utils/ethTools.js"); + +// const nullAddress = "0x0000000000000000000000000000000000000000"; +// // get etherum accounts +// // swap ether with LOT +// let airdrop; +// contract("Airdrop", async function([user1, user2, user3, user4, user5, user6, user7, user8, user9, user10]) { +// it("Place the prediction with ether", async () => { +// masterInstance = await OwnedUpgradeabilityProxy.deployed(); +// masterInstance = await Master.at(masterInstance.address); +// plotusToken = await PlotusToken.deployed(); +// BLOTInstance = await BLOT.at(await masterInstance.getLatestAddress(web3.utils.toHex("BL"))); +// MockUniswapRouterInstance = await MockUniswapRouter.deployed(); +// plotusNewAddress = await masterInstance.getLatestAddress(web3.utils.toHex("PL")); +// tokenController =await TokenController.at(await masterInstance.getLatestAddress(web3.utils.toHex("TC"))); +// plotusNewInstance = await Plotus.at(plotusNewAddress); +// marketConfig = await plotusNewInstance.marketUtility(); +// marketConfig = await MarketConfig.at(marketConfig); +// // console.log(await plotusNewInstance.getOpenMarkets()); +// openMarkets = await plotusNewInstance.getOpenMarkets(); +// let endDate = (await latestTime())/1+(24*3600); +// airdrop = await Airdrop.new(plotusToken.address, BLOTInstance.address, endDate, toWei("1000")); + +// await BLOTInstance.addMinter(airdrop.address); + +// await plotusToken.transfer(airdrop.address,toWei("1000")); + +// await airdrop.airdropBLot([user2,user4],["400000000000000000000","124000000000000000000"]); + + +// // console.log(`OpenMaket : ${openMarkets["_openMarkets"][0]}`); + +// marketInstance = await Market.at(openMarkets["_openMarkets"][0]); +// await increaseTime(10001); +// assert.ok(marketInstance); + +// // setting option price in eth +// await marketConfig.setOptionPrice(1, 9); +// await marketConfig.setOptionPrice(2, 18); +// await marketConfig.setOptionPrice(3, 27); + +// await assertRevert(marketInstance.calculatePredictionResult(1)); //should revert as market is in live status + +// // set price +// // user 1 +// // set price lot +// await MockUniswapRouterInstance.setPrice("1000000000000000"); +// await marketConfig.setPrice("1000000000000000"); +// await plotusToken.approve(tokenController.address, "100000000000000000000", { +// from: user1, +// }); +// await marketInstance.placePrediction(plotusToken.address, "100000000000000000000", 2, 1, { from: user1 }); + +// // user 2 +// await MockUniswapRouterInstance.setPrice("2000000000000000"); +// await marketConfig.setPrice("2000000000000000"); +// // await plotusToken.transfer(user2, "500000000000000000000"); + +// // await plotusToken.approve( +// // openMarkets["_openMarkets"][0], +// // "400000000000000000000", +// // { +// // from: user2, +// // } +// // ); +// // await marketInstance.placePrediction( +// // plotusToken.address, +// // "400000000000000000000", +// // 2, +// // 2, +// // { from: user2 } +// // ); +// await plotusToken.approve(BLOTInstance.address, "4000000000000000000000"); +// // await BLOTInstance.mint(user2, "400000000000000000000"); +// await airdrop.claim({from:user2}); + +// // await BLOTInstance.transferFrom(user1, user2, "500000000000000000000", { +// // from: user1, +// // }); + +// // await BLOTInstance.approve(openMarkets["_openMarkets"][0], "400000000000000000000", { +// // from: user2, +// // }); +// // console.log(await BLOTInstance.balanceOf(user1)); +// // await BLOTInstance.addMinter(marketInstance.address); +// await marketInstance.placePrediction(BLOTInstance.address, "400000000000000000000", 2, 5, { from: user2 }); +// let flags = await marketInstance.getUserFlags(user2); +// assert.equal(flags[1], true); +// // user 3 +// await MockUniswapRouterInstance.setPrice("1000000000000000"); +// await marketConfig.setPrice("1000000000000000"); +// await plotusToken.transfer(user3, "500000000000000000000"); +// await plotusToken.approve(tokenController.address, "210000000000000000000", { +// from: user3, +// }); + +// await assertRevert(marketInstance.placePrediction(user10, "210000000000000000000", 2, 2, { from: user3 })); //should revert as assert not valid +// await assertRevert(marketInstance.placePrediction(plotusToken.address, "210000000000000000000", 2, 2, { from: user3, value: "100" })); // should revert as passing value +// await assertRevert(marketInstance.placePrediction(plotusToken.address, "1", 2, 2, { from: user3 })); // should revert as prediction amount is less than min required prediction +// // try { +// // await marketInstance.placePrediction(plotusToken.address, "600000000000000000000", 2, 2, { from: user3 }); // should revert as user do not have enough asset +// // assert.fail(); +// // } catch (e) { +// // console.log(e); +// // } + +// await marketInstance.placePrediction(plotusToken.address, "210000000000000000000", 2, 2, { from: user3 }); +// // user 4 +// await MockUniswapRouterInstance.setPrice("15000000000000000"); +// await marketConfig.setPrice("15000000000000000"); + +// await plotusToken.approve(BLOTInstance.address, "124000000000000000000"); +// // await BLOTInstance.mint(user4, "124000000000000000000"); +// await airdrop.claim({from:user4}); + +// // await BLOTInstance.approve(openMarkets["_openMarkets"][0], "124000000000000000000", { +// // from: user4, +// // }); + +// await assertRevert(marketInstance.placePrediction(BLOTInstance.address, "123000000000000000000", 3, 4, { from: user4 })); //should revert as leverage is not 5 +// await assertRevert( +// marketInstance.placePrediction(BLOTInstance.address, "123000000000000000000", 3, 5, { from: user4, value: "1000000000000000000" }) +// ); // should revert as passing value + +// await marketInstance.placePrediction(BLOTInstance.address, "123000000000000000000", 3, 5, { from: user4 }); + +// await assertRevert(marketInstance.placePrediction(BLOTInstance.address, "1000000000000000000", 3, 5, { from: user4 })); //should revert as once usr can only place prediction with BLOT once in a market + +// // await plotusToken.transfer(user4, "200000000000000000000"); + +// // await plotusToken.approve( +// // openMarkets["_openMarkets"][0], +// // "123000000000000000000", +// // { +// // from: user4, +// // } +// // ); +// // await marketInstance.placePrediction( +// // plotusToken.address, +// // "123000000000000000000", +// // 3, +// // 3, +// // { from: user4 } +// // ); + +// // user 5 +// await MockUniswapRouterInstance.setPrice("12000000000000000"); +// await marketConfig.setPrice("12000000000000000"); +// await assertRevert( +// marketInstance.placePrediction("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", "1000000000000000000", 1, 4, { +// value: "100000000000000000", +// from: user5, +// }) +// ); +// await marketInstance.placePrediction("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", "1000000000000000000", 1, 4, { +// value: "1000000000000000000", +// from: user5, +// }); + +// // user 6 +// await MockUniswapRouterInstance.setPrice("14000000000000000"); +// await marketConfig.setPrice("14000000000000000"); +// await marketInstance.placePrediction("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", "2000000000000000000", 1, 5, { +// value: "2000000000000000000", +// from: user6, +// }); +// // user 7 +// await MockUniswapRouterInstance.setPrice("10000000000000000"); +// await marketConfig.setPrice("10000000000000000"); + +// await marketInstance.placePrediction("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", "1000000000000000000", 2, 2, { +// value: "1000000000000000000", +// from: user7, +// }); +// // user 8 +// await MockUniswapRouterInstance.setPrice("45000000000000000"); +// await marketConfig.setPrice("45000000000000000"); +// await marketInstance.placePrediction("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", "3000000000000000000", 3, 3, { +// value: "3000000000000000000", +// from: user8, +// }); +// // user 9 +// await MockUniswapRouterInstance.setPrice("51000000000000000"); +// await marketConfig.setPrice("51000000000000000"); +// await marketInstance.placePrediction("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", "1000000000000000000", 3, 1, { +// value: "1000000000000000000", +// from: user9, +// }); +// // user 10 +// await MockUniswapRouterInstance.setPrice("12000000000000000"); +// await marketConfig.setPrice("12000000000000000"); +// await marketInstance.placePrediction("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", "2000000000000000000", 2, 4, { +// value: "2000000000000000000", +// from: user10, +// }); +// }); + +// it("1.Prediction Points allocated properly in ether", async () => { +// accounts = [user1, user2, user3, user4, user5, user6, user7, user8, user9, user10]; +// options = [2, 2, 2, 3, 1, 1, 2, 3, 3, 2]; +// getPredictionPoints = async (user, option, expected) => { +// // return Prediction points of user +// let PredictionPoins = await marketInstance.getUserPredictionPoints(user, option); +// PredictionPoins = PredictionPoins / 1; +// return PredictionPoins; +// }; +// PredictionPointsExpected = [1.755503471, 238.3350545, 11.21889102, 556.4885586, 510.3, 1882.8, 116.5, 634.1, 37.0, 721.7]; + +// // console.log("Prediction points for user 1"); +// // PredictionPointsUser1 = await getPredictionPoints(accounts[0], options[0]); +// // PredictionPointsUser3 = await getPredictionPoints(accounts[2], options[2]); + +// // console.log( +// // `Prediction points : ${PredictionPointsUser1} expected : ${PredictionPointsExpected[0]} ` +// // ); +// // console.log("Prediction points for user 3"); +// // console.log( +// // `Prediction points : ${PredictionPointsUser3} expected : ${PredictionPointsExpected[2]} ` +// // ); +// for (let index = 0; index < 10; index++) { +// let PredictionPoints = await getPredictionPoints(accounts[index], options[index]); +// PredictionPoints = PredictionPoints / 1000; +// PredictionPoints = PredictionPoints.toFixed(1); +// assert.equal(PredictionPoints, PredictionPointsExpected[index].toFixed(1)); +// // commented by parv (as already added assert above) +// // console.log(`user${index + 1} : option : ${options[index]} `); +// // console.log(`Prediction points : ${PredictionPoints} expected : ${PredictionPointsExpected[index].toFixed(1)} `); +// } +// // console.log(await plotusToken.balanceOf(user1)); + +// // close market +// await increaseTime(36001); +// await marketInstance.calculatePredictionResult(1); +// await increaseTime(36001); +// // console.log((await web3.eth.getBalance(marketInstance.address))/1) +// // plotus contract balance eth balance +// plotusBalanceBefore = await web3.eth.getBalance(plotusNewAddress); +// assert.equal(parseFloat(plotusBalanceBefore), "10000000000000000"); +// lotBalanceBefore = await plotusToken.balanceOf(openMarkets["_openMarkets"][0]); +// assert.equal(parseFloat(web3.utils.fromWei(lotBalanceBefore)).toFixed(2), (832.5835).toFixed(2)); + +// // lot supply , lot balance of market +// await MockUniswapRouterInstance.setPrice("1000000000000000"); +// await marketConfig.setPrice("1000000000000000"); + + +// plotusBalanceAfter = await web3.eth.getBalance(plotusNewAddress); +// assert.equal(parseFloat(plotusBalanceAfter), 10000000000000000); +// lotBalanceAfter = await plotusToken.balanceOf(openMarkets["_openMarkets"][0]); +// assert.equal(parseFloat(web3.utils.fromWei(lotBalanceAfter)).toFixed(2), (832.5835).toFixed(2)); +// // assert.equal(parseFloat(web3.utils.fromWei(String(parseFloat(lotBalanceAfter) - parseFloat(lotBalanceBefore)))).toFixed(2), (4.5835).toFixed(2)); +// // commented by Parv (as asserts already added above) +// // lotBalanceBefore = lotBalanceBefore / 1; +// // lotBalanceAfter = lotBalanceAfter / 1; +// // console.log(`plotus eth balance before commision : ${plotusBalanceBefore}`); +// // console.log(`plotus balance after commision : ${plotusBalanceAfter}`); +// // console.log(`Lot Balance of market before commision : ${lotBalanceBefore}`); +// // console.log(`Lot Balance of market before commision : ${lotBalanceAfter}`); +// // console.log(`Difference : ${lotBalanceAfter - lotBalanceBefore}`); +// }); + +// it("2.check total return for each user Prediction values in eth", async () => { +// accounts = [user1, user2, user3, user4, user5, user6, user7, user8, user9, user10]; +// options = [2, 2, 2, 3, 1, 1, 2, 3, 3, 2]; +// getReturnsInEth = async (user) => { +// // return userReturn in eth +// const response = await marketInstance.getReturn(user); +// let returnAmountInEth = web3.utils.fromWei(response[0][1]); +// return returnAmountInEth; +// }; + +// const returnInEthExpected = [0, 0, 0, 0, 1.851161356, 5.141838644, 0.5994, 1.1988, 0.7992, 0.3996]; +// // calulate rewards for every user in eth + +// // console.log("Rewards in Eth"); +// for (let index = 0; index < 10; index++) { +// // check eth returns +// let returns = await getReturnsInEth(accounts[index]); +// assert.equal(parseFloat(returns).toFixed(2), returnInEthExpected[index].toFixed(2)); +// // commented by Parv (as assert already added above) +// // console.log(`return : ${returns} Expected :${returnInEthExpected[index]}`); +// } +// }); +// it("3.Check User Recived The appropriate amount", async () => { +// accounts = [user1, user2, user3, user4, user5, user6, user7, user8, user9, user10]; +// const totalReturnLotExpexted = [79.96, 0, 125.937, 0, 133.6431475, 493.0463525, 0, 0, 0, 0]; +// const returnInEthExpected = [0, 0, 0, 0, 1.851161356, 5.141838644, 0.5994, 1.1988, 0.7992, 0.3996]; +// for (let account of accounts) { +// beforeClaim = await web3.eth.getBalance(account); +// beforeClaimToken = await plotusToken.balanceOf(account); +// await marketInstance.claimReturn(account); +// afterClaim = await web3.eth.getBalance(account); +// afterClaimToken = await plotusToken.balanceOf(account); +// diff = afterClaim - beforeClaim; +// diff = new BigNumber(diff); +// conv = new BigNumber(1000000000000000000); +// diff = diff / conv; +// diff = diff.toFixed(2); +// // expectedInEth = returnInEthExpected[accounts.indexOf(account)].toFixed(2); +// // assert.equal(diff, expectedInEth); + +// diffToken = afterClaimToken - beforeClaimToken; +// diffToken = diffToken / conv; +// diffToken = diffToken.toFixed(2); +// expectedInLot = totalReturnLotExpexted[accounts.indexOf(account)].toFixed(2); +// assert.equal(diffToken, expectedInLot); + +// // commented by Parv (as assert already added above) +// // console.log(`User ${accounts.indexOf(account) + 1}`); +// // console.log(`Returned in Eth : ${diff} Expected : ${expectedInEth} `); +// // console.log(`Returned in Lot : ${diffToken} Expected : ${expectedInLot} `); +// } +// }); +// }); +// contract("Market", async function([user1, user2]) { +// let masterInstance, BLOTInstance; +// it("Test BLOT Contract", async () => { +// masterInstance = await OwnedUpgradeabilityProxy.deployed(); +// masterInstance = await Master.at(masterInstance.address); +// plotusToken = await PlotusToken.deployed(); +// BLOTInstance = await BLOT.at(await masterInstance.getLatestAddress(web3.utils.toHex("BL"))); +// MockUniswapRouterInstance = await MockUniswapRouter.deployed(); +// plotusNewAddress = await masterInstance.getLatestAddress(web3.utils.toHex("PL")); +// plotusNewInstance = await Plotus.at(plotusNewAddress); +// marketConfig = await plotusNewInstance.marketUtility(); +// marketConfig = await MarketConfig.at(marketConfig); + + +// let isMinter = await BLOTInstance.isMinter(user1); + +// assert.equal(isMinter, true); + +// isMinter = await BLOTInstance.isMinter(user2); +// assert.equal(isMinter, false); +// receipt = await BLOTInstance.addMinter(user2); +// isMinter = await BLOTInstance.isMinter(user2); +// assert.equal(isMinter, true); +// assert.equal(receipt.logs[0].event, "MinterAdded"); +// assert.equal(receipt.logs[0].args.account, user2); + +// receipt = await BLOTInstance.renounceMinter({ from: user2 }); +// isMinter = await BLOTInstance.isMinter(user2); +// assert.equal(isMinter, false); +// assert.equal(receipt.logs[0].event, "MinterRemoved"); +// assert.equal(receipt.logs[0].args.account, user2); + +// await assertRevert(BLOTInstance.mint(user2, 100)); +// try { +// await BLOTInstance.transfer("0x0000000000000000000000000000000000000000", 10, { from: user1 }); +// assert.fail(); +// } catch (e) {} +// }); +// }); + +// contract("More cases for airdrop", async function([user1, user2]) { +// it("Should Revert if deployed with null address as plot token, blot token", async () => { +// let endDate = (await latestTime())/1+(24*3600); +// await assertRevert(Airdrop.new(nullAddress, user1, endDate, toWei(10))); +// await assertRevert(Airdrop.new(user1, nullAddress, endDate, toWei(10))); +// }); +// it("Should Revert if deployed with past time as end date", async () => { +// let endDate = (await latestTime())/1-(24); +// await assertRevert(Airdrop.new(user1, user1, endDate, toWei(10))); +// }); +// it("Should Revert if non owner calls airdropBLot, user array have different length than amount array", async () => { +// let endDate = (await latestTime())/1+(24*3600); +// let _airdrop = await Airdrop.new(plotusToken.address, BLOTInstance.address, endDate, toWei(100)); +// await assertRevert(_airdrop.airdropBLot([],[],{from:user2})); +// await assertRevert(_airdrop.airdropBLot([user1,user2],[toWei(10)])); +// }); +// it("Should Revert if tries to allocate after end date, null address in user list, 0 amount in amount list", async () => { +// let endDate = (await latestTime())/1+(24*3600); +// let _airdrop = await Airdrop.new(plotusToken.address, BLOTInstance.address, endDate, toWei(10)); +// await assertRevert(_airdrop.airdropBLot([nullAddress],[toWei(10)])); +// await assertRevert(_airdrop.airdropBLot([user1],[0])); +// await increaseTime(24*3600); +// await assertRevert(_airdrop.airdropBLot([user1],[toWei(10)])); +// }); +// it("Should Revert if tries to allocate multiple times to same user, non owner tries to call takeLeftOverPlot, tries to call takeLeftOverPlot before end date", async () => { +// let endDate = (await latestTime())/1+(24*3600); +// let _airdrop = await Airdrop.new(plotusToken.address, BLOTInstance.address, endDate, toWei(100)); +// await assertRevert(_airdrop.takeLeftOverPlot()); +// await assertRevert(_airdrop.takeLeftOverPlot({from:user2})); +// await _airdrop.airdropBLot([user1],[toWei(10)]); +// await assertRevert(_airdrop.airdropBLot([user1],[toWei(10)])); +// }); +// it("Should Revert if tries to claim after end date, user can not claim multiple time", async () => { +// let endDate = (await latestTime())/1+(24*3600); +// let _airdrop = await Airdrop.new(plotusToken.address, BLOTInstance.address, endDate, toWei(100)); +// await _airdrop.airdropBLot([user1],[toWei(10)]); +// await plotusToken.transfer(_airdrop.address, toWei(30)); +// await BLOTInstance.addMinter(_airdrop.address); +// await _airdrop.claim({from:user1}); +// await assertRevert(_airdrop.claim({from:user1})); +// await increaseTime(24*3600); +// await assertRevert(_airdrop.claim({from:user1})); +// }); +// it("Should be able to take back plot toekens after end date", async () => { +// let endDate = (await latestTime())/1+(24*3600); +// let _airdrop = await Airdrop.new(plotusToken.address, BLOTInstance.address, endDate, toWei(100)); +// await plotusToken.transfer(_airdrop.address, toWei(30)); +// await increaseTime(24*3600); +// await _airdrop.takeLeftOverPlot(); +// assert.equal(await plotusToken.balanceOf(_airdrop.address), 0); +// }); +// it("Owner should be able to transfer ownership to other address", async () => { +// let endDate = (await latestTime())/1+(24*3600); +// let _airdrop = await Airdrop.new(plotusToken.address, BLOTInstance.address, endDate, toWei(100)); +// assert.equal(await _airdrop.owner(), user1); +// await _airdrop.tranferOwnership(user2); +// assert.equal(await _airdrop.owner(), user2); +// }); +// it("Should revert if tries to transfer ownership to null address", async () => { +// let endDate = (await latestTime())/1+(24*3600); +// let _airdrop = await Airdrop.new(plotusToken.address, BLOTInstance.address, endDate, toWei(100)); +// await assertRevert(_airdrop.tranferOwnership(nullAddress)); +// }); +// it("Should revert if tries to allocate more than budget", async () => { +// let endDate = (await latestTime())/1+(24*3600); +// let _airdrop = await Airdrop.new(plotusToken.address, BLOTInstance.address, endDate, toWei(100)); +// await _airdrop.airdropBLot([user1],[toWei(50)]); +// await assertRevert(_airdrop.airdropBLot([user2],[toWei(51)])); +// }); +// }); diff --git a/test/basic_test.js b/test/basic_test.js new file mode 100644 index 000000000..c580783ab --- /dev/null +++ b/test/basic_test.js @@ -0,0 +1,232 @@ +const { assert } = require("chai"); +const OwnedUpgradeabilityProxy = artifacts.require("OwnedUpgradeabilityProxy"); +const Market = artifacts.require("MockMarket"); +const Plotus = artifacts.require("MarketRegistry"); +const Master = artifacts.require("Master"); +const MemberRoles = artifacts.require("MemberRoles"); +const PlotusToken = artifacts.require("MockPLOT"); +const MockWeth = artifacts.require("MockWeth"); +const MarketUtility = artifacts.require("MarketUtilityV2"); +const MockConfig = artifacts.require("MockConfig"); +const Governance = artifacts.require("Governance"); +const AllMarkets = artifacts.require("AllMarkets"); +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 {toHex, toWei, toChecksumAddress} = require('./utils/ethTools'); +const gvProposal = require('./utils/gvProposal.js').gvProposalWithIncentiveViaTokenHolder; + +var initialPLOTPrice; +var initialEthPrice; +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, allMarkets; + 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 Markets 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("Should not allow to re initialize Utility after updating Implementation", async function() { + await assertRevert(marketConfig.initialize([user1, MockUniswapRouterInstance.address, plotusToken.address, mockUniswapFactory.address], user1)) + }); + + 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(); + }); + + // it("Check price of plot", async function() { + // await increaseTime(3610); + // await assertRevert(plotusNewInstance.createMarket(0,0)); + // await marketConfig.setInitialCummulativePrice(); + // await assertRevert(marketConfig.setInitialCummulativePrice()); + // await mockUniswapV2Pair.sync(); + // await increaseTime(3610); + // await plotusNewInstance.createMarket(0,0); + // let currentPrice = (await marketConfig.getPrice(mockUniswapV2Pair.address, toWei(1)))/1; + // assert.equal(initialEthPrice, currentPrice/1e18); + // await plotusNewInstance.createMarket(0,1); + // await increaseTime(3610); + // await mockUniswapV2Pair.sync(); + // await plotusNewInstance.createMarket(0,0); + // await increaseTime(3610); + // await mockUniswapV2Pair.sync(); + // currentPrice = (await marketConfig.getPrice(mockUniswapV2Pair.address, toWei(1)))/1; + // assert.equal(initialEthPrice, currentPrice/1e18); + // let plotPriceInEth = ((await marketConfig.getAssetPriceInETH(plotusToken.address))[0])/1; + // assert.equal(initialEthPrice, plotPriceInEth/1e18); + // let ethPriceInEth = ((await marketConfig.getAssetPriceInETH(ethAddress))[0])/1; + // assert.equal(ethPriceInEth, 1); + // }); + + it('Should add AllMarkets as new contract in Master', 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("Create market in new contract", async function() { + allMarkets = await AllMarkets.new(); + await allMarkets.initiate(plotusToken.address, marketConfig.address); + await increaseTime(3610); + var date = await latestTime(); + date = Math.round(date) + await marketConfig.setInitialCummulativePrice(); + await marketConfig.setAuthorizedAddress(allMarkets.address); + let utility = await MarketUtility.at(marketConfig.address); + await utility.setAuthorizedAddress(allMarkets.address); + await mockUniswapV2Pair.sync(); + await allMarkets.addInitialMarketTypesAndStart(date, "0x5e2aa6b66531142bEAB830c385646F97fa03D80a"); + await increaseTime(7200); + console.log(await allMarkets.marketData(0)); + let tx = await allMarkets.createMarket(0, 0); + console.log(tx); + }); + + it("Place Prediction", async function() { + // let tx = await allMarkets.createMarket(0,000), 3600); + // await assertRevert(marketInstance.placePrediction("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", "1000000000000000000", 2, 4, { + // value: "1000000000000000000", + // from: user10 + // })); + console.log(plotusToken.address); + await plotusToken.transfer(user10, toWei(1000)); + await plotusToken.transfer(user11, toWei(1000)); + await plotusToken.approve(allMarkets.address, toWei(100000), {from:user10}); + await plotusToken.approve(allMarkets.address, toWei(100000), {from:user11}); + await allMarkets.deposit(toWei(1000), {value: "2100000000000000000", from:user10}) + await allMarkets.deposit(toWei(1000), {value: "1000000000000000000", from:user11}) + await plotusToken.approve(tokenController.address, toWei(100000), {from:user10}); + tx = await plotusToken.approve(tokenController.address, toWei(100000), {from:user11}); + tx = await allMarkets.placePrediction(1, "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", "1000000000000000000", 2, { + from: user10 + }); + console.log("*****************************************"); + console.log("1st market 1st pred"); + console.log(tx); + console.log("*****************************************"); + tx = await allMarkets.placePrediction(1, plotusToken.address, "10000000000000000000", 1, { + from: user10 + }); + console.log("*****************************************"); + console.log("1st market 2nd pred"); + console.log(tx); + console.log("*****************************************"); + await increaseTime(7300); + await allMarkets.createMarket(0, 0); + tx = await allMarkets.placePrediction(2, "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", "100000000000000000", 2, { + from: user10 + }); + console.log("*****************************************"); + console.log("2nd market 1st pred"); + console.log(tx); + console.log("*****************************************"); + await increaseTime(10000); + await allMarkets.createMarket(0, 0); + tx = await allMarkets.placePrediction(3, "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", "100000000000000000", 2, { + from: user10 + }); + tx = await allMarkets.placePrediction(3, plotusToken.address, "10000000000000000000", 1, { + from: user11 + }); + console.log("*****************************************"); + console.log("3rd market 2nd pred"); + console.log(tx); + console.log("*****************************************"); + }); + + it("Claim Rewards", async function() { + await allMarkets.deposit(0, {value: "10000000000000000000", from:user10}); + let tx; + for(let i= 0; i<30; i++) { + await increaseTime(7200); + tx = await allMarkets.createMarket(0, 0); + await allMarkets.placePrediction(i + 4, "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", "100000000000000000", 2, { + from: user10 + }); + } + console.log(tx); + console.log((await web3.eth.getBalance(user10))/1); + tx = await allMarkets.withdraw(30, {from:user10}); + console.log((await web3.eth.getBalance(user10))/1); + console.log(tx); + // await assertRevert(allMarkets.claimCreationReward()); + // await plotusToken.transfer(allMarkets.address, toWei(1000)); + // tx = await allMarkets.claimCreationReward(); + // console.log(tx); + }) + +}); diff --git a/test/bets-multipleOptionsSheet.test.js b/test/bets-multipleOptionsSheet.test.js new file mode 100644 index 000000000..1ec7e2c1b --- /dev/null +++ b/test/bets-multipleOptionsSheet.test.js @@ -0,0 +1,540 @@ +const { assert } = require("chai"); +const OwnedUpgradeabilityProxy = artifacts.require("OwnedUpgradeabilityProxy"); +const Master = artifacts.require("Master"); +const MemberRoles = artifacts.require("MemberRoles"); +const PlotusToken = artifacts.require("MockPLOT"); +const MockConfig = artifacts.require("MockConfig"); //mock +const Governance = artifacts.require("Governance"); +const AllMarkets = artifacts.require("MockAllMarkets"); +const TokenController = artifacts.require("MockTokenController"); +const MockChainLinkAggregator = artifacts.require("MockChainLinkAggregator"); +const MarketCreationRewards = artifacts.require('MarketCreationRewards'); + +const ethAddress = "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE"; +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 encode3 = require("./utils/encoder.js").encode3; +const gvProposal = require("./utils/gvProposal.js").gvProposalWithIncentiveViaTokenHolder; +const { toHex, toWei, toChecksumAddress } = require("./utils/ethTools"); +const signAndExecuteMetaTx = require("./utils/signAndExecuteMetaTx.js").signAndExecuteMetaTx; +const to8Power = (number) => String(parseFloat(number) * 1e8); +let privateKeyList = ["fb437e3e01939d9d4fef43138249f23dc1d0852e69b0b5d1647c087f869fabbd","7c85a1f1da3120c941b83d71a154199ee763307683f206b98ad92c3b4e0af13e","ecc9b35bf13bd5459350da564646d05c5664a7476fe5acdf1305440f88ed784c","f4470c3fca4dbef1b2488d016fae25978effc586a1f83cb29ac8cb6ab5bc2d50","141319b1a84827e1046e93741bf8a9a15a916d49684ab04925ac4ce4573eea23","d54b606094287758dcf19064a8d91c727346aadaa9388732e73c4315b7c606f9","49030e42ce4152e715a7ddaa10e592f8e61d00f70ef11f48546711f159d985df","b96761b1e7ebd1e8464a78a98fe52f53ce6035c32b4b2b12307a629a551ff7cf","d4786e2581571c863c7d12231c3afb6d4cef390c0ac9a24b243293721d28ea95","ed28e3d3530544f1cf2b43d1956b7bd13b63c612d963a8fb37387aa1a5e11460","05b127365cf115d4978a7997ee98f9b48f0ddc552b981c18aa2ee1b3e6df42c6","9d11dd6843f298b01b34bd7f7e4b1037489871531d14b58199b7cba1ac0841e6","f79e90fa4091de4fc2ec70f5bf67b24393285c112658e0d810e6bd711387fbb9","99f1fc0f09230ce745b6a256ba7082e6e51a2907abda3d9e735a5c8188bb4ba1","477f86cce983b9c91a36fdcd4a7ce21144a08dee9b1aafb91b9c70e57f717ce6","b03d2e6bb4a7d71c66a66ff9e9c93549cae4b593f634a4ea2a1f79f94200f5b4","9ddc0f53a81e631dcf39d5155f41ec12ed551b731efc3224f410667ba07b37dc","cf087ff9ae7c9954ad8612d071e5cdf34a6024ee1ae477217639e63a802a53dd","b64f62b94babb82cc78d3d1308631ae221552bb595202fc1d267e1c29ce7ba60","a91e24875f8a534497459e5ccb872c4438be3130d8d74b7e1104c5f94cdcf8c2","4f49f3d029eeeb3fed14d59625acd088b6b34f3b41c527afa09d29e4a7725c32","179795fd7ac7e7efcba3c36d539a1e8659fb40d77d0a3fab2c25562d99793086","4ba37d0b40b879eceaaca2802a1635f2e6d86d5c31e3ff2d2fd13e68dd2a6d3d","6b7f5dfba9cd3108f1410b56f6a84188eee23ab48a3621b209a67eea64293394","870c540da9fafde331a3316cee50c17ad76ddb9160b78b317bef2e6f6fc4bac0","470b4cccaea895d8a5820aed088357e380d66b8e7510f0a1ea9b575850160241","8a55f8942af0aec1e0df3ab328b974a7888ffd60ded48cc6862013da0f41afbc","2e51e8409f28baf93e665df2a9d646a1bf9ac8703cbf9a6766cfdefa249d5780","99ef1a23e95910287d39493d8d9d7d1f0b498286f2b1fdbc0b01495f10cf0958","6652200c53a4551efe2a7541072d817562812003f9d9ef0ec17995aa232378f8","39c6c01194df72dda97da2072335c38231ced9b39afa280452afcca901e73643","12097e411d948f77b7b6fa4656c6573481c1b4e2864c1fca9d5b296096707c45","cbe53bf1976aee6cec830a848c6ac132def1503cffde82ccfe5bd15e75cbaa72","eeab5dcfff92dbabb7e285445aba47bd5135a4a3502df59ac546847aeb5a964f","5ea8279a578027abefab9c17cef186cccf000306685e5f2ee78bdf62cae568dd","0607767d89ad9c7686dbb01b37248290b2fa7364b2bf37d86afd51b88756fe66","e4fd5f45c08b52dae40f4cdff45e8681e76b5af5761356c4caed4ca750dc65cd","145b1c82caa2a6d703108444a5cf03e9cb8c3cd3f19299582a564276dbbba734","736b22ec91ae9b4b2b15e8d8c220f6c152d4f2228f6d46c16e6a9b98b4733120","ac776cb8b40f92cdd307b16b83e18eeb1fbaa5b5d6bd992b3fda0b4d6de8524c","65ba30e2202fdf6f37da0f7cfe31dfb5308c9209885aaf4cef4d572fd14e2903","54e8389455ec2252de063e83d3ce72529d674e6d2dc2070661f01d4f76b63475","fbbbfb525dd0255ee332d51f59648265aaa20c2e9eff007765cf4d4a6940a849","8de5e418f34d04f6ea947ce31852092a24a705862e6b810ca9f83c2d5f9cda4d","ea6040989964f012fd3a92a3170891f5f155430b8bbfa4976cde8d11513b62d9","14d94547b5deca767137fbd14dae73e888f3516c742fad18b83be333b38f0b88","47f05203f6368d56158cda2e79167777fc9dcb0c671ef3aabc205a1636c26a29"]; + +describe("Bets Multiple options sheet", () => { + contract("AllMarket", async function ([user1, user2, user3, user4, user5, user6, userMarketCreator]) { + // Multiplier Sheet + let masterInstance, + plotusToken, + mockMarketConfig, + MockUniswapRouterInstance, + tokenControllerAdd, + tokenController, + plotusNewAddress, + plotusNewInstance, + governance, + allMarkets, + marketUtility, + mockChainLinkAggregator; + let marketId = 1; + let predictionPointsBeforeUser1, predictionPointsBeforeUser2, predictionPointsBeforeUser3, predictionPointsBeforeUser4; + 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); + 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); + mockMarketConfig = await MockConfig.at(await masterInstance.getLatestAddress(web3.utils.toHex("MU"))); + allMarkets = await AllMarkets.at(await masterInstance.getLatestAddress(web3.utils.toHex("AM"))); + marketId = 6; + await increaseTime(4 * 60 * 60); + await allMarkets.createMarket(0, 0, { from: userMarketCreator }); + marketId++; + }); + it("3.1 Scenario 1: player purchase 2 position in same option, in same currency and wins", async () => { + await plotusToken.transfer(user2, toWei("400")); + await plotusToken.transfer(user3, toWei("400")); + + await plotusToken.approve(allMarkets.address, toWei("10000"), { from: user1 }); + await plotusToken.approve(allMarkets.address, toWei("10000"), { from: user2 }); + await plotusToken.approve(allMarkets.address, toWei("10000"), { from: user3 }); + await allMarkets.deposit(toWei(500), { from: user1 }); + await allMarkets.deposit(toWei(400), { from: user2 }); + await allMarkets.deposit(toWei(400), { from: user3 }); + + await mockMarketConfig.setNextOptionPrice(90); + let functionSignature = encode3("depositAndPlacePrediction(uint,uint,address,uint64,uint256)", 0, marketId, plotusToken.address, to8Power("100"), 1); + await signAndExecuteMetaTx( + privateKeyList[0], + user1, + functionSignature, + allMarkets + ); + // await allMarkets.depositAndPlacePrediction(, { from: user1 }); + functionSignature = encode3("depositAndPlacePrediction(uint,uint,address,uint64,uint256)", 0, marketId, plotusToken.address, to8Power("400"), 1); + await signAndExecuteMetaTx( + privateKeyList[0], + user1, + functionSignature, + allMarkets + ); + // await allMarkets.depositAndPlacePrediction(0, marketId, plotusToken.address, to8Power("400"), 1, { from: user1 }); + functionSignature = encode3("depositAndPlacePrediction(uint,uint,address,uint64,uint256)", 0, marketId, plotusToken.address, to8Power("400"), 1); + await signAndExecuteMetaTx( + privateKeyList[1], + user2, + functionSignature, + allMarkets + ); + // await allMarkets.depositAndPlacePrediction(0, marketId, plotusToken.address, to8Power("400"), 1, { from: user2 }); + await mockMarketConfig.setNextOptionPrice(180); + functionSignature = encode3("depositAndPlacePrediction(uint,uint,address,uint64,uint256)", 0, marketId, plotusToken.address, to8Power("400"), 2); + await signAndExecuteMetaTx( + privateKeyList[2], + user3, + functionSignature, + allMarkets + ); + // await allMarkets.depositAndPlacePrediction(0, marketId, plotusToken.address, to8Power("400"), 2, { from: user3 }); + + predictionPointsBeforeUser1 = parseFloat(await allMarkets.getUserPredictionPoints(user1, marketId, 1)) / 1e5; + predictionPointsBeforeUser2 = parseFloat(await allMarkets.getUserPredictionPoints(user2, marketId, 1)) / 1e5; + predictionPointsBeforeUser3 = parseFloat(await allMarkets.getUserPredictionPoints(user3, marketId, 2)) / 1e5; + + + // console.log(predictionPointsBeforeUser1, predictionPointsBeforeUser2, predictionPointsBeforeUser3); + const expectedPredictionPoints = [1110.555556 + 4442.222222, 4353.377778, 2176.688889]; + const expectedPLOTReturn = [143.6545942 + 574.6183767, 563.1260091, 0]; + const expectedETHReturn = [0, 0, 0]; + + const predictionPointArray = [ + predictionPointsBeforeUser1, + predictionPointsBeforeUser2, + predictionPointsBeforeUser3, + ]; + + await increaseTime(8 * 60 * 60); + await allMarkets.postResultMock(1, marketId); + await increaseTime(8 * 60 * 60); + + let returnUser1 = (await allMarkets.getReturn(user1, marketId)) / 1e8; + let returnUser2 = (await allMarkets.getReturn(user2, marketId)) / 1e8; + let returnUser3 = (await allMarkets.getReturn(user3, marketId)) / 1e8; + const plotReturn = [returnUser1, returnUser2, returnUser3] + + await allMarkets.withdraw(toWei(returnUser1), 10, { from: user1 }); + await allMarkets.withdraw(toWei(returnUser2), 10, { from: user2 }); + await assertRevert(allMarkets.withdraw(toWei(returnUser3), 10, { from: user3 })); + + // console.log( // (await plotusToken.balanceOf(user1)) / 1e18, // (await plotusToken.balanceOf(user2)) / 1e18, // (await plotusToken.balanceOf(user3)) / 1e18, // (await plotusToken.balanceOf(user4)) / 1e18, // (await plotusToken.balanceOf(user5)) / 1e18 // ); // console.log( // (await web3.eth.getBalance(user1)) / 1e18, // (await web3.eth.getBalance(user2)) / 1e18, // (await web3.eth.getBalance(user3)) / 1e18, // (await web3.eth.getBalance(user4)) / 1e18, // (await web3.eth.getBalance(user5)) / 1e18 // ); + + for (let i = 0; i < 3; i++) { + assert.equal(expectedPredictionPoints[i].toFixed(1), predictionPointArray[i].toFixed(1)); + assert.equal(expectedPLOTReturn[i].toFixed(3), plotReturn[i].toFixed(3)) + // assert.equal(expectedETHReturn[i].toFixed(3), ethReturn[i].toFixed(3)) + } + }); + it("3.2. Scenario 2", async () => { + await allMarkets.createMarket(0, 0); + marketId++; + + await plotusToken.transfer(user2, toWei("400")); + await plotusToken.transfer(user3, toWei("400")); + + await plotusToken.approve(allMarkets.address, toWei("10000"), { from: user1 }); + await plotusToken.approve(allMarkets.address, toWei("10000"), { from: user2 }); + await plotusToken.approve(allMarkets.address, toWei("10000"), { from: user3 }); + await allMarkets.deposit(toWei(500), { from: user1 }); + await allMarkets.deposit(toWei(400), { from: user2 }); + await allMarkets.deposit(toWei(400), { from: user3 }); + + await mockMarketConfig.setNextOptionPrice(90); + await allMarkets.depositAndPlacePrediction(0, marketId, plotusToken.address, to8Power("400"), 1, { from: user2 }); + await mockMarketConfig.setNextOptionPrice(180); + await allMarkets.depositAndPlacePrediction(0, marketId, plotusToken.address, to8Power("100"), 2, { from: user1 }); + await allMarkets.depositAndPlacePrediction(0, marketId, plotusToken.address, to8Power("400"), 2, { from: user1 }); + await allMarkets.depositAndPlacePrediction(0, marketId, plotusToken.address, to8Power("400"), 2, { from: user3 }); + + predictionPointsBeforeUser1 = parseFloat(await allMarkets.getUserPredictionPoints(user1, marketId, 2)) / 1e5; + predictionPointsBeforeUser2 = parseFloat(await allMarkets.getUserPredictionPoints(user2, marketId, 1)) / 1e5; + predictionPointsBeforeUser3 = parseFloat(await allMarkets.getUserPredictionPoints(user3, marketId, 2)) / 1e5; + + // console.log(predictionPointsBeforeUser1, predictionPointsBeforeUser2, predictionPointsBeforeUser3); + const expectedPredictionPoints = [555.2777778 + 2221.111111, 4442.222222, 2221.111111]; + const expectedPLOTReturn = [0 + 0, 1294.85225, 0]; + const expectedETHReturn = [0, 0, 0]; + + const predictionPointArray = [ + predictionPointsBeforeUser1, + predictionPointsBeforeUser2, + predictionPointsBeforeUser3, + ]; + + await increaseTime(8 * 60 * 60); + await allMarkets.postResultMock(1, marketId); + await increaseTime(8 * 60 * 60); + + let returnUser1 = (await allMarkets.getReturn(user1, marketId)) / 1e8; + let returnUser2 = (await allMarkets.getReturn(user2, marketId)) / 1e8; + let returnUser3 = (await allMarkets.getReturn(user3, marketId)) / 1e8; + const plotReturn = [returnUser1, returnUser2, returnUser3] + + await allMarkets.withdraw(toWei(returnUser2), 10, { from: user2 }); + await assertRevert(allMarkets.withdraw(toWei(returnUser1), 10, { from: user1 })); + await assertRevert(allMarkets.withdraw(toWei(returnUser3), 10, { from: user3 })); + + // console.log( // (await plotusToken.balanceOf(user1)) / 1e18, // (await plotusToken.balanceOf(user2)) / 1e18, // (await plotusToken.balanceOf(user3)) / 1e18, // (await plotusToken.balanceOf(user4)) / 1e18, // (await plotusToken.balanceOf(user5)) / 1e18 // ); // console.log( // (await web3.eth.getBalance(user1)) / 1e18, // (await web3.eth.getBalance(user2)) / 1e18, // (await web3.eth.getBalance(user3)) / 1e18, // (await web3.eth.getBalance(user4)) / 1e18, // (await web3.eth.getBalance(user5)) / 1e18 // ); + + for (let i = 0; i < 3; i++) { + assert.equal(expectedPredictionPoints[i].toFixed(1), predictionPointArray[i].toFixed(1)); + assert.equal(expectedPLOTReturn[i].toFixed(3), plotReturn[i].toFixed(3)) + // assert.equal(expectedETHReturn[i].toFixed(3), ethReturn[i].toFixed(3)) + } + }); + it("3.3. Scenario 3", async () => { + await allMarkets.createMarket(0, 0); + marketId++; + + await plotusToken.transfer(user2, toWei("400")); + await plotusToken.transfer(user3, toWei("400")); + + await plotusToken.approve(allMarkets.address, toWei("10000"), { from: user1 }); + await plotusToken.approve(allMarkets.address, toWei("10000"), { from: user2 }); + await plotusToken.approve(allMarkets.address, toWei("10000"), { from: user3 }); + await allMarkets.deposit(toWei(500), { from: user1 }); + await allMarkets.deposit(toWei(400), { from: user2 }); + await allMarkets.deposit(toWei(400), { from: user3 }); + + await mockMarketConfig.setNextOptionPrice(90); + await allMarkets.depositAndPlacePrediction(0, marketId, plotusToken.address, to8Power("100"), 1, { from: user1 }); + await allMarkets.depositAndPlacePrediction(0, marketId, plotusToken.address, to8Power("400"), 1, { from: user2 }); + + await mockMarketConfig.setNextOptionPrice(180); + await allMarkets.depositAndPlacePrediction(0, marketId, plotusToken.address, to8Power("400"), 2, { from: user1 }); + await allMarkets.depositAndPlacePrediction(0, marketId, plotusToken.address, to8Power("400"), 2, { from: user3 }); + + predictionPointsBeforeUser1 = parseFloat(await allMarkets.getUserPredictionPoints(user1, marketId, 1)) / 1e5; + predictionPointsBeforeUser1_2 = parseFloat(await allMarkets.getUserPredictionPoints(user1, marketId, 2)) / 1e5; + predictionPointsBeforeUser2 = parseFloat(await allMarkets.getUserPredictionPoints(user2, marketId, 1)) / 1e5; + predictionPointsBeforeUser3 = parseFloat(await allMarkets.getUserPredictionPoints(user3, marketId, 2)) / 1e5; + + // console.log(predictionPointsBeforeUser1, predictionPointsBeforeUser1_2, predictionPointsBeforeUser2, predictionPointsBeforeUser3); + const expectedPredictionPoints = [1110.555556, 2221.111111, 4442.222222, 2221.111111]; + const expectedETHReturn = [0, 0, 0]; + const expectedPLOTReturn = [259.0704, 1036.2816, 0]; + + const predictionPointArray = [ + predictionPointsBeforeUser1, + predictionPointsBeforeUser1_2, + predictionPointsBeforeUser2, + predictionPointsBeforeUser3, + ]; + + await increaseTime(8 * 60 * 60); + await allMarkets.postResultMock(1, marketId); + await increaseTime(8 * 60 * 60); + + let returnUser1 = (await allMarkets.getReturn(user1, marketId)) / 1e8; + let returnUser2 = (await allMarkets.getReturn(user2, marketId)) / 1e8; + let returnUser3 = (await allMarkets.getReturn(user3, marketId)) / 1e8; + const plotReturn = [returnUser1, returnUser2, returnUser3] + + // console.log( // (await plotusToken.balanceOf(user1)) / 1e18, // (await plotusToken.balanceOf(user2)) / 1e18, // (await plotusToken.balanceOf(user3)) / 1e18, // (await plotusToken.balanceOf(user4)) / 1e18, // (await plotusToken.balanceOf(user5)) / 1e18 // ); // console.log( // (await web3.eth.getBalance(user1)) / 1e18, // (await web3.eth.getBalance(user2)) / 1e18, // (await web3.eth.getBalance(user3)) / 1e18, // (await web3.eth.getBalance(user4)) / 1e18, // (await web3.eth.getBalance(user5)) / 1e18 // ); + + await allMarkets.withdraw(toWei(returnUser1), 10, { from: user1 }); + await allMarkets.withdraw(toWei(returnUser2), 10, { from: user2 }); + await assertRevert(allMarkets.withdraw(toWei(returnUser2), 10, { from: user3 })); + + // console.log( // (await plotusToken.balanceOf(user1)) / 1e18, // (await plotusToken.balanceOf(user2)) / 1e18, // (await plotusToken.balanceOf(user3)) / 1e18, // (await plotusToken.balanceOf(user4)) / 1e18, // (await plotusToken.balanceOf(user5)) / 1e18 // ); // console.log( // (await web3.eth.getBalance(user1)) / 1e18, // (await web3.eth.getBalance(user2)) / 1e18, // (await web3.eth.getBalance(user3)) / 1e18, // (await web3.eth.getBalance(user4)) / 1e18, // (await web3.eth.getBalance(user5)) / 1e18 // ); + for (let i = 0; i < 4; i++) { + assert.equal(expectedPredictionPoints[i].toFixed(1), predictionPointArray[i].toFixed(1)); + } + + for (let i = 0; i < 3; i++) { + assert.equal(expectedPLOTReturn[i].toFixed(3), plotReturn[i].toFixed(3)) + // assert.equal(expectedETHReturn[i].toFixed(3), ethReturn[i].toFixed(3)) + } + }); + // it("3.4. Scenario 4", async () => { + // await allMarkets.createMarket(0, 0); + // marketId++; + + // await plotusToken.transfer(user2, toWei("400")); + // await plotusToken.transfer(user3, toWei("400")); + + // await plotusToken.approve(allMarkets.address, toWei("10000"), { from: user1 }); + // await plotusToken.approve(allMarkets.address, toWei("10000"), { from: user2 }); + // await plotusToken.approve(allMarkets.address, toWei("10000"), { from: user3 }); + // await allMarkets.deposit(0, { value: toWei(4), from: user1 }); + // await allMarkets.deposit(toWei(400), { from: user1 }); + // await allMarkets.deposit(toWei(400), { from: user2 }); + // await allMarkets.deposit(toWei(400), { from: user3 }); + + // await mockMarketConfig.setNextOptionPrice(90); + // await allMarkets.placePrediction(marketId, ethAddress, to8Power("4"), 1, { from: user1 }); + // await allMarkets.placePrediction(marketId, plotusToken.address, to8Power("400"), 1, { from: user1 }); + + // await mockMarketConfig.setNextOptionPrice(180); + // await allMarkets.placePrediction(marketId, plotusToken.address, to8Power("400"), 2, { from: user3 }); + + // await mockMarketConfig.setNextOptionPrice(270); + // await allMarkets.placePrediction(marketId, plotusToken.address, to8Power("400"), 3, { from: user2 }); + + + // predictionPointsBeforeUser1 = parseFloat(await allMarkets.getUserPredictionPoints(user1, marketId, 1)) / 1e5; + // predictionPointsBeforeUser2 = parseFloat(await allMarkets.getUserPredictionPoints(user2, marketId, 3)) / 1e5; + // predictionPointsBeforeUser3 = parseFloat(await allMarkets.getUserPredictionPoints(user3, marketId, 2)) / 1e5; + + // // console.log(predictionPointsBeforeUser1, predictionPointsBeforeUser2, predictionPointsBeforeUser3); + + // const expectedPredictionPoints = [44.4 + 44.42222222, 14.80740741, 22.21111111]; + // const expectedETHReturn = [3.996 + 0, 0, 0]; + // const expectedPLOTReturn = [397.7014751 + 797.7005249, 0, 0]; + + // const predictionPointArray = [ + // predictionPointsBeforeUser1, + // predictionPointsBeforeUser2, + // predictionPointsBeforeUser3, + // ]; + + // await increaseTime(8 * 60 * 60); + // await allMarkets.postResultMock(1, marketId); + // await increaseTime(8 * 60 * 60); + + // let returnUser1 = (await allMarkets.getReturn(user1, marketId))[0][0] / 1e8; + // let returnUser2 = (await allMarkets.getReturn(user2, marketId))[0][0] / 1e8; + // let returnUser3 = (await allMarkets.getReturn(user3, marketId))[0][0] / 1e8; + // const plotReturn = [returnUser1, returnUser2, returnUser3] + + // let returnETHUser1 = (await allMarkets.getReturn(user1, marketId))[0][1] / 1e8; + // let returnETHUser2 = (await allMarkets.getReturn(user2, marketId))[0][1] / 1e8; + // let returnETHUser3 = (await allMarkets.getReturn(user3, marketId))[0][1] / 1e8; + // const ethReturn = [returnETHUser1, returnETHUser2, returnETHUser3] + + // // console.log( // (await plotusToken.balanceOf(user1)) / 1e18, // (await plotusToken.balanceOf(user2)) / 1e18, // (await plotusToken.balanceOf(user3)) / 1e18, // (await plotusToken.balanceOf(user4)) / 1e18, // (await plotusToken.balanceOf(user5)) / 1e18 // ); // console.log( // (await web3.eth.getBalance(user1)) / 1e18, // (await web3.eth.getBalance(user2)) / 1e18, // (await web3.eth.getBalance(user3)) / 1e18, // (await web3.eth.getBalance(user4)) / 1e18, // (await web3.eth.getBalance(user5)) / 1e18 // ); + + // await allMarkets.withdrawMax(10, { from: user1 }); + // await assertRevert(allMarkets.withdrawMax(10, { from: user2 })); + // await assertRevert(allMarkets.withdrawMax(10, { from: user3 })); + + // // console.log( // (await plotusToken.balanceOf(user1)) / 1e18, // (await plotusToken.balanceOf(user2)) / 1e18, // (await plotusToken.balanceOf(user3)) / 1e18, // (await plotusToken.balanceOf(user4)) / 1e18, // (await plotusToken.balanceOf(user5)) / 1e18 // ); // console.log( // (await web3.eth.getBalance(user1)) / 1e18, // (await web3.eth.getBalance(user2)) / 1e18, // (await web3.eth.getBalance(user3)) / 1e18, // (await web3.eth.getBalance(user4)) / 1e18, // (await web3.eth.getBalance(user5)) / 1e18 // ); + + // for (let i = 0; i < 3; i++) { + // assert.equal(expectedPredictionPoints[i].toFixed(1), predictionPointArray[i].toFixed(1)); + // assert.equal(expectedPLOTReturn[i].toFixed(3), plotReturn[i].toFixed(3)) + // assert.equal(expectedETHReturn[i].toFixed(3), ethReturn[i].toFixed(3)) + // } + // }); + // it("3.5. Scenario 5", async () => { + // await allMarkets.createMarket(0, 0); + // marketId++; + + // await plotusToken.transfer(user2, toWei("400")); + // await plotusToken.transfer(user3, toWei("400")); + + // await plotusToken.approve(allMarkets.address, toWei("10000"), { from: user1 }); + // await plotusToken.approve(allMarkets.address, toWei("10000"), { from: user2 }); + // await plotusToken.approve(allMarkets.address, toWei("10000"), { from: user3 }); + // await allMarkets.deposit(toWei(100), { from: user1 }); + // await allMarkets.deposit(0, { value: toWei(4), from: user1 }); + // await allMarkets.deposit(toWei(400), { from: user2 }); + // await allMarkets.deposit(toWei(400), { from: user3 }); + + // await mockMarketConfig.setNextOptionPrice(90); + // await allMarkets.placePrediction(marketId, plotusToken.address, to8Power("400"), 1, { from: user3 }); + + // await mockMarketConfig.setNextOptionPrice(180); + // await allMarkets.placePrediction(marketId, plotusToken.address, to8Power("100"), 2, { from: user1 }); + // await allMarkets.placePrediction(marketId, ethAddress, to8Power("4"), 2, { from: user1 }); + + // await mockMarketConfig.setNextOptionPrice(270); + // await allMarkets.placePrediction(marketId, plotusToken.address, to8Power("400"), 3, { from: user2 }); + + // predictionPointsBeforeUser1 = parseFloat(await allMarkets.getUserPredictionPoints(user1, marketId, 2)) / 1e5; + // predictionPointsBeforeUser2 = parseFloat(await allMarkets.getUserPredictionPoints(user2, marketId, 3)) / 1e5; + // predictionPointsBeforeUser3 = parseFloat(await allMarkets.getUserPredictionPoints(user3, marketId, 1)) / 1e5; + + // // console.log(predictionPointsBeforeUser1, predictionPointsBeforeUser1_2, predictionPointsBeforeUser2, predictionPointsBeforeUser3); + + // const expectedPredictionPoints = [5.552777778 + 22.2, 14.80740741, 44.42222222]; + // const expectedETHReturn = [0 + 0, 0, 3.97602]; + // const expectedPLOTReturn = [0 + 0, 0, 897.05125]; + + // const predictionPointArray = [ + // predictionPointsBeforeUser1, + // predictionPointsBeforeUser2, + // predictionPointsBeforeUser3, + // ]; + + // await increaseTime(8 * 60 * 60); + // await allMarkets.postResultMock(1, marketId); + // await increaseTime(8 * 60 * 60); + + // let returnUser1 = (await allMarkets.getReturn(user1, marketId))[0][0] / 1e8; + // let returnUser2 = (await allMarkets.getReturn(user2, marketId))[0][0] / 1e8; + // let returnUser3 = (await allMarkets.getReturn(user3, marketId))[0][0] / 1e8; + // const plotReturn = [returnUser1, returnUser2, returnUser3] + + // let returnETHUser1 = (await allMarkets.getReturn(user1, marketId))[0][1] / 1e8; + // let returnETHUser2 = (await allMarkets.getReturn(user2, marketId))[0][1] / 1e8; + // let returnETHUser3 = (await allMarkets.getReturn(user3, marketId))[0][1] / 1e8; + // const ethReturn = [returnETHUser1, returnETHUser2, returnETHUser3] + + // // console.log( // (await plotusToken.balanceOf(user1)) / 1e18, // (await plotusToken.balanceOf(user2)) / 1e18, // (await plotusToken.balanceOf(user3)) / 1e18, // (await plotusToken.balanceOf(user4)) / 1e18, // (await plotusToken.balanceOf(user5)) / 1e18 // ); // console.log( // (await web3.eth.getBalance(user1)) / 1e18, // (await web3.eth.getBalance(user2)) / 1e18, // (await web3.eth.getBalance(user3)) / 1e18, // (await web3.eth.getBalance(user4)) / 1e18, // (await web3.eth.getBalance(user5)) / 1e18 // ); + + // await assertRevert(allMarkets.withdrawMax(10, { from: user1 })); + // await assertRevert(allMarkets.withdrawMax(10, { from: user2 })); + // await allMarkets.withdrawMax(10, { from: user3 }); + + // // console.log( // (await plotusToken.balanceOf(user1)) / 1e18, // (await plotusToken.balanceOf(user2)) / 1e18, // (await plotusToken.balanceOf(user3)) / 1e18, // (await plotusToken.balanceOf(user4)) / 1e18, // (await plotusToken.balanceOf(user5)) / 1e18 // ); // console.log( // (await web3.eth.getBalance(user1)) / 1e18, // (await web3.eth.getBalance(user2)) / 1e18, // (await web3.eth.getBalance(user3)) / 1e18, // (await web3.eth.getBalance(user4)) / 1e18, // (await web3.eth.getBalance(user5)) / 1e18 // ); + + // for (let i = 0; i < 3; i++) { + // assert.equal(expectedPredictionPoints[i].toFixed(1), predictionPointArray[i].toFixed(1)); + // assert.equal(expectedPLOTReturn[i].toFixed(3), plotReturn[i].toFixed(3)) + // assert.equal(expectedETHReturn[i].toFixed(3), ethReturn[i].toFixed(3)) + // } + // }); + it("3.6. Scenario 6,7 and 8", async () => { + await increaseTime(604800); + await allMarkets.createMarket(0, 2); + marketId++; + const scenario6MarketId = marketId; + + await plotusToken.transfer(user2, toWei("400")); + await plotusToken.transfer(user3, toWei("400")); + + await plotusToken.approve(allMarkets.address, toWei("10000"), { from: user1 }); + await plotusToken.approve(allMarkets.address, toWei("10000"), { from: user2 }); + await plotusToken.approve(allMarkets.address, toWei("10000"), { from: user3 }); + await allMarkets.deposit(toWei(500), { from: user1 }); + await allMarkets.deposit(toWei(400), { from: user2 }); + await allMarkets.deposit(toWei(400), { from: user3 }); + + await mockMarketConfig.setNextOptionPrice(90); + await allMarkets.depositAndPlacePrediction(0, marketId, plotusToken.address, to8Power("100"), 1, { from: user1 }); + await allMarkets.depositAndPlacePrediction(0, marketId, plotusToken.address, to8Power("400"), 1, { from: user2 }); + + await mockMarketConfig.setNextOptionPrice(180); + await allMarkets.depositAndPlacePrediction(0, marketId, plotusToken.address, to8Power("400"), 2, { from: user1 }); + await allMarkets.depositAndPlacePrediction(0, marketId, plotusToken.address, to8Power("400"), 2, { from: user3 }); + + await allMarkets.createMarket(0, 0); + marketId++; + const scenario7MarketId = marketId; + + await plotusToken.transfer(user1, toWei("100")); + await plotusToken.transfer(user2, toWei("400")); + await plotusToken.transfer(user3, toWei("500")); + + await plotusToken.approve(allMarkets.address, toWei("10000"), { from: user1 }); + await plotusToken.approve(allMarkets.address, toWei("10000"), { from: user2 }); + await plotusToken.approve(allMarkets.address, toWei("10000"), { from: user3 }); + await allMarkets.deposit(toWei(200), { from: user1 }); + await allMarkets.deposit(toWei(400), { from: user2 }); + await allMarkets.deposit(toWei(500), { from: user3 }); + + await mockMarketConfig.setNextOptionPrice(90); + await allMarkets.depositAndPlacePrediction(0, marketId, plotusToken.address, to8Power("100"), 1, { from: user1 }); + await allMarkets.depositAndPlacePrediction(0, marketId, plotusToken.address, to8Power("500"), 1, { from: user3 }); + await mockMarketConfig.setNextOptionPrice(180); + await allMarkets.depositAndPlacePrediction(0, marketId, plotusToken.address, to8Power("100"), 2, { from: user1 }); + await mockMarketConfig.setNextOptionPrice(270); + await allMarkets.depositAndPlacePrediction(0, marketId, plotusToken.address, to8Power("400"), 3, { from: user2 }); + + await allMarkets.createMarket(1, 0); + marketId++; + const scenario8MarketId = marketId; + + await plotusToken.transfer(user1, toWei("400")); + await plotusToken.transfer(user2, toWei("400")); + await plotusToken.transfer(user3, toWei("400")); + + await plotusToken.approve(allMarkets.address, toWei("10000"), { from: user1 }); + await plotusToken.approve(allMarkets.address, toWei("10000"), { from: user2 }); + await plotusToken.approve(allMarkets.address, toWei("10000"), { from: user3 }); + await allMarkets.deposit(toWei(400), { from: user1 }); + await allMarkets.deposit(toWei(400), { from: user2 }); + await allMarkets.deposit(toWei(200), { from: user3 }); + + await mockMarketConfig.setNextOptionPrice(90); + await allMarkets.depositAndPlacePrediction(0, marketId, plotusToken.address, to8Power("100"), 1, { from: user1 }); + await allMarkets.depositAndPlacePrediction(0, marketId, plotusToken.address, to8Power("200"), 1, { from: user3 }); + + await mockMarketConfig.setNextOptionPrice(180); + await allMarkets.depositAndPlacePrediction(0, marketId, plotusToken.address, to8Power("300"), 2, { from: user1 }); + + await mockMarketConfig.setNextOptionPrice(270); + await allMarkets.depositAndPlacePrediction(0, marketId, plotusToken.address, to8Power("400"), 3, { from: user2 }); + + await increaseTime(8 * 60 * 60); + let neutralMinValue = (await allMarkets.getMarketData(scenario7MarketId)).neutralMinValue / 1; + let neutralMaxValue = (await allMarkets.getMarketData(scenario7MarketId)).neutralMaxValue / 1; + let betweenNeutral = neutralMaxValue - 100; + await allMarkets.postResultMock(String(betweenNeutral), scenario7MarketId); + neutralMaxValue = (await allMarkets.getMarketData(scenario8MarketId)).neutralMaxValue / 1; + await allMarkets.postResultMock(String(neutralMaxValue + 1), scenario8MarketId); + await increaseTime(8 * 60 * 60); + + + let plotBalanceBeforeUser1 = (await plotusToken.balanceOf(user1)) / 1e18; + let plotBalanceBeforeUser2 = (await plotusToken.balanceOf(user2)) / 1e18; + let plotBalanceBeforeUser3 = (await plotusToken.balanceOf(user3)) / 1e18; + + let ethBalanceBeforeUser1 = (await web3.eth.getBalance(user1)) / 1e18; + let ethBalanceBeforeUser2 = (await web3.eth.getBalance(user2)) / 1e18; + let ethBalanceBeforeUser3 = (await web3.eth.getBalance(user3)) / 1e18; + + let user1Balance = await allMarkets.getUserUnusedBalance(user1); + user1Balance = user1Balance[0] + user1Balance[1]; + let user2Balance = await allMarkets.getUserUnusedBalance(user2); + user2Balance = user2Balance[0] + user2Balance[1]; + let user3Balance = await allMarkets.getUserUnusedBalance(user3); + user3Balance = user3Balance[0] + user3Balance[1]; + await allMarkets.withdraw(user1Balance, 10, { from: user1 }); + await allMarkets.withdraw(user2Balance, 10, { from: user2 }); + await assertRevert(allMarkets.withdraw(user3Balance, 10, { from: user3 })); + + let plotBalanceAfterUser1 = (await plotusToken.balanceOf(user1)) / 1e18; + let plotBalanceAfterUser2 = (await plotusToken.balanceOf(user2)) / 1e18; + let plotBalanceAfterUser3 = (await plotusToken.balanceOf(user3)) / 1e18; + + assert.equal((plotBalanceAfterUser1-plotBalanceBeforeUser1).toFixed(2), (1094.4525).toFixed(2)) + assert.equal((plotBalanceAfterUser2-plotBalanceBeforeUser2).toFixed(2), (996.5015).toFixed(2)) + + await increaseTime(60 * 60 * 24 * 14); + await allMarkets.postResultMock(1, scenario6MarketId); + await increaseTime(60 * 60 * 24 * 6); + + plotBalanceBeforeUser1 = (await plotusToken.balanceOf(user1)) / 1e18; + plotBalanceBeforeUser2 = (await plotusToken.balanceOf(user2)) / 1e18; + plotBalanceBeforeUser3 = (await plotusToken.balanceOf(user3)) / 1e18; + + user1Balance = await allMarkets.getUserUnusedBalance(user1); + user1Balance = user1Balance[0] + user1Balance[1]; + user2Balance = await allMarkets.getUserUnusedBalance(user2); + user2Balance = user2Balance[0] + user2Balance[1]; + user3Balance = await allMarkets.getUserUnusedBalance(user3); + user3Balance = user3Balance[0] + user3Balance[1]; + await allMarkets.withdraw(user1Balance, 10, { from: user1 }); + await allMarkets.withdraw(user2Balance, 10, { from: user2 }); + await assertRevert(allMarkets.withdraw(user3Balance, 10, { from: user3 })); + + // await allMarkets.withdrawMax(10, { from: user1 }); + // await allMarkets.withdrawMax(10, { from: user2 }); + // await assertRevert(allMarkets.withdrawMax(10, { from: user3 })); + + plotBalanceAfterUser1 = (await plotusToken.balanceOf(user1)) / 1e18; + plotBalanceAfterUser2 = (await plotusToken.balanceOf(user2)) / 1e18; + plotBalanceAfterUser3 = (await plotusToken.balanceOf(user3)) / 1e18; + + assert.equal((plotBalanceAfterUser1-plotBalanceBeforeUser1).toFixed(2), (259.0704).toFixed(2)) + assert.equal((plotBalanceAfterUser2-plotBalanceBeforeUser2).toFixed(2), (1036.2816).toFixed(2)) + + }); + }); +}); \ No newline at end of file diff --git a/test/newOptionPrice.test.js b/test/newOptionPrice.test.js new file mode 100644 index 000000000..87551d895 --- /dev/null +++ b/test/newOptionPrice.test.js @@ -0,0 +1,207 @@ +const { assert } = require("chai"); +const OwnedUpgradeabilityProxy = artifacts.require("OwnedUpgradeabilityProxy"); +const Market = artifacts.require("MockMarket"); +const Plotus = artifacts.require("MarketRegistry"); +const Master = artifacts.require("Master"); +const MemberRoles = artifacts.require("MemberRoles"); +const PlotusToken = artifacts.require("MockPLOT"); +const MockWeth = artifacts.require("MockWeth"); +const MockConfig = artifacts.require("MockConfig"); +const Governance = artifacts.require("Governance"); +const AllMarkets = artifacts.require("AllMarkets"); +const MarketCreationRewards = artifacts.require("MarketCreationRewards"); +const MockUniswapRouter = artifacts.require("MockUniswapRouter"); +const MockUniswapV2Pair = artifacts.require("MockUniswapV2Pair"); +const MockUniswapFactory = artifacts.require("MockUniswapFactory"); +const TokenController = artifacts.require("MockTokenController"); +const MockChainLinkAggregator = artifacts.require("MockChainLinkAggregator"); + +const web3 = Market.web3; +const ethAddress = "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE"; +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 gvProposal = require("./utils/gvProposal.js").gvProposalWithIncentiveViaTokenHolder; +const { toHex, toWei, toChecksumAddress } = require("./utils/ethTools"); +const to8Power = (number) => String(parseFloat(number) * 1e8); + +describe("Sheet- New Pricing.", () => { + let masterInstance, + plotusToken, + marketConfig, + MockUniswapRouterInstance, + tokenControllerAdd, + tokenController, + plotusNewAddress, + plotusNewInstance, + governance, + mockUniswapV2Pair, + mockUniswapFactory, + weth, + allMarkets, + mockChainLinkAggregator; + let marketId = 1; + contract("AllMarkets", async function ([user1, user2, user3, user4, user5, userMarketCreator]) { + 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); + let newUtility = await MockConfig.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 MockConfig.at(marketConfig.address); + mockUniswapV2Pair = await MockUniswapV2Pair.new(); + await mockUniswapV2Pair.initialize(plotusToken.address, weth.address); + await weth.deposit({ from: user4, value: toWei(10) }); + await weth.transfer(mockUniswapV2Pair.address, toWei(10), { from: user4 }); + await plotusToken.transfer(mockUniswapV2Pair.address, toWei(1000)); + initialPLOTPrice = 1000 / 10; + initialEthPrice = 10 / 1000; + await mockUniswapFactory.setPair(mockUniswapV2Pair.address); + await mockUniswapV2Pair.sync(); + newUtility = await MockConfig.new(); + existingMarkets = await plotusNewInstance.getOpenMarkets(); + 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 MockConfig.at(marketConfig.address); + allMarkets = await AllMarkets.at(await masterInstance.getLatestAddress(web3.utils.toHex("AM"))); + var date = Date.now(); + date = Math.round(date / 1000) + 10000; + await marketConfig.setInitialCummulativePrice(); + await marketConfig.setAuthorizedAddress(allMarkets.address); + let utility = await MockConfig.at("0xCBc7df3b8C870C5CDE675AaF5Fd823E4209546D2"); + await utility.setAuthorizedAddress(allMarkets.address); + await mockUniswapV2Pair.sync(); + let mcr; + let _marketUtility = await plotusNewInstance.marketUtility(); + mockChainLinkAggregator = await MockChainLinkAggregator.new(); + await marketConfig.setMockPriceFlag(false); + allMarkets = await AllMarkets.at(await masterInstance.getLatestAddress(web3.utils.toHex("AM"))); + mcr = await MarketCreationRewards.at(await masterInstance.getLatestAddress(web3.utils.toHex("MC"))); + + marketId = 6; + await increaseTime(4 * 60 * 60 + 1); + await allMarkets.createMarket(0, 0, { from: userMarketCreator }); + marketId++; + }); + it("Test Case 1", async () => { + await marketConfig.setMaxPredictionValue(toWei(2000)); + await marketConfig.setMockPriceFlag(false); + + assert.equal((await allMarkets.getMarketData(marketId))._optionPrice[0] / 1, 100); + assert.equal((await allMarkets.getMarketData(marketId))._optionPrice[1] / 1, 100); + assert.equal((await allMarkets.getMarketData(marketId))._optionPrice[2] / 1, 100); + await MockUniswapRouterInstance.setPrice(toWei(0.01)); + await marketConfig.setPrice(toWei(0.01)); + + assert.equal(Math.round((await allMarkets.getUserPredictionPoints(user1, marketId, 1)) / 1e3), 0); + assert.equal(Math.round((await allMarkets.getUserPredictionPoints(user1, marketId, 2)) / 1e3), 0); + assert.equal(Math.round((await allMarkets.getUserPredictionPoints(user1, marketId, 3)) / 1e3), 0); + + await plotusToken.approve(allMarkets.address, toWei("2000000000"), { from: user1 }); + }); + it("Test Case 2", async () => { + await allMarkets.deposit(0, { from: user1, value: toWei("1") }); + await allMarkets.placePrediction(marketId, ethAddress, to8Power("1"), 2, { from: user1 }); + + assert.equal(Math.round((await allMarkets.getUserPredictionPoints(user1, marketId, 1)) / 1e3), 0); + assert.equal(Math.round((await allMarkets.getUserPredictionPoints(user1, marketId, 2)) / 1e3), 999); + assert.equal(Math.round((await allMarkets.getUserPredictionPoints(user1, marketId, 3)) / 1e3), 0); + + assert.equal((await allMarkets.getMarketData(marketId))._optionPrice[0] / 1, 100); + assert.equal((await allMarkets.getMarketData(marketId))._optionPrice[1] / 1, 200); + assert.equal((await allMarkets.getMarketData(marketId))._optionPrice[2] / 1, 100); + }); + it("Test Case 3", async () => { + await marketConfig.setMaxPredictionValue(toWei("100000000")); + await allMarkets.deposit(0, { from: user1, value: toWei("100") }); + await allMarkets.placePrediction(marketId, ethAddress, to8Power("100"), 1, { from: user1 }); + + assert.equal(Math.round((await allMarkets.getUserPredictionPoints(user1, marketId, 1)) / 1e3), 99900); + assert.equal(Math.round((await allMarkets.getUserPredictionPoints(user1, marketId, 2)) / 1e3), 999); + assert.equal(Math.round((await allMarkets.getUserPredictionPoints(user1, marketId, 3)) / 1e3), 0); + + assert.equal((await allMarkets.getMarketData(marketId))._optionPrice[0] / 1, (Math.round(1.99 * 1e2) / 1e2) * 1e2); + assert.equal((await allMarkets.getMarketData(marketId))._optionPrice[1] / 1, (Math.round(1.00 * 1e2) / 1e2) * 1e2); + assert.equal((await allMarkets.getMarketData(marketId))._optionPrice[2] / 1, 1 * 1e2); + }); + it("Test Case 4", async () => { + await allMarkets.deposit(0, { from: user1, value: toWei("0.01") }); + await allMarkets.placePrediction(marketId, ethAddress, to8Power("0.01"), 3, { from: user1 }); + + assert.equal(Math.round((await allMarkets.getUserPredictionPoints(user1, marketId, 1)) / 1e3), 99900); + assert.equal(Math.round((await allMarkets.getUserPredictionPoints(user1, marketId, 2)) / 1e3), 999); + assert.equal(Math.round((await allMarkets.getUserPredictionPoints(user1, marketId, 3)) / 1e3), Math.round(9.99)); + + assert.equal((await allMarkets.getMarketData(marketId))._optionPrice[0] / 1, (Math.round(1.99 * 1e2) / 1e2) * 1e2); + assert.equal((await allMarkets.getMarketData(marketId))._optionPrice[1] / 1, (Math.round(1.00 * 1e2) / 1e2) * 1e2); + assert.equal((await allMarkets.getMarketData(marketId))._optionPrice[2] / 1, (Math.round(1.00 * 1e2) / 1e2) * 1e2); + }); + it("Test Case 5", async () => { + await allMarkets.deposit(toWei("100"), { from: user1 }); + await allMarkets.placePrediction(marketId, plotusToken.address, to8Power("100"), 1, { from: user1 }); + + assert.equal(Math.round(Math.round((await allMarkets.getUserPredictionPoints(user1, marketId, 1)) / 1e3)), 100402); + assert.equal(Math.round((await allMarkets.getUserPredictionPoints(user1, marketId, 2)) / 1e3), 999); + assert.equal(Math.round((await allMarkets.getUserPredictionPoints(user1, marketId, 3)) / 1e3), Math.round(9.99)); + + assert.equal((await allMarkets.getMarketData(marketId))._optionPrice[0] / 1, (Math.round(1.99 * 1e2) / 1e2) * 1e2); + assert.equal((await allMarkets.getMarketData(marketId))._optionPrice[1] / 1, (Math.round(1.00 * 1e2) / 1e2) * 1e2); + assert.equal((await allMarkets.getMarketData(marketId))._optionPrice[2] / 1, (Math.round(1.00 * 1e2) / 1e2) * 1e2); + }); + it("Test Case 6", async () => { + await allMarkets.deposit(toWei("10000000"), { from: user1 }); + await allMarkets.placePrediction(marketId, plotusToken.address, to8Power("10000000"), 2, { from: user1 }); + + assert.equal(Math.round((await allMarkets.getUserPredictionPoints(user1, marketId, 1)) / 1e3), 100402); + assert.equal(Math.round((await allMarkets.getUserPredictionPoints(user1, marketId, 2)) / 1e3), 99950999); + assert.equal(Math.round((await allMarkets.getUserPredictionPoints(user1, marketId, 3)) / 1e3), Math.round(9.99)); + + assert.equal((await allMarkets.getMarketData(marketId))._optionPrice[0] / 1, (Math.round(1.001013886 * 1e2) / 1e2) * 1e2); + assert.equal((await allMarkets.getMarketData(marketId))._optionPrice[1] / 1, (Math.round(1.99 * 1e2) / 1e2) * 1e2); + assert.equal((await allMarkets.getMarketData(marketId))._optionPrice[2] / 1, (Math.round(1.000000101 * 1e2) / 1e2) * 1e2); + }); + it("Test Case 7", async () => { + await allMarkets.deposit(toWei("978546.56"), { from: user1 }); + await allMarkets.placePrediction(marketId, plotusToken.address, to8Power("978546.56"), 3, { from: user1 }); + + assert.equal(Math.round((await allMarkets.getUserPredictionPoints(user1, marketId, 1)) / 1e3), 100402); + assert.equal(Math.round((await allMarkets.getUserPredictionPoints(user1, marketId, 2)) / 1e3), 99950999); + assert.equal(Math.round((await allMarkets.getUserPredictionPoints(user1, marketId, 3)) / 1e3), Math.round(9780582.859)); + + assert.equal((await allMarkets.getMarketData(marketId))._optionPrice[0] / 1, (Math.round(1.000922791 * 1e2) / 1e2) * 1e2); + assert.equal((await allMarkets.getMarketData(marketId))._optionPrice[1] / 1, (Math.round(1.91 * 1e2) / 1e2) * 1e2); + assert.equal((await allMarkets.getMarketData(marketId))._optionPrice[2] / 1, (Math.round(1.08 * 1e2) / 1e2) * 1e2); + }); + // it("Test Case 8", async () => { + // await allMarkets.deposit(0, { from: user1, value: toWei("1456.98") }); + // await allMarkets.placePrediction(marketId, ethAddress, to8Power("1456.98"), 1, { from: user1 }); + + // assert.equal(Math.round((await allMarkets.getUserPredictionPoints(user1, marketId, 1)) / 1e3), 1554583); + // assert.equal(Math.round((await allMarkets.getUserPredictionPoints(user1, marketId, 2)) / 1e3), 99950999); + // assert.equal(Math.round((await allMarkets.getUserPredictionPoints(user1, marketId, 3)) / 1e3), Math.round(9780582.859)); + + // assert.equal((await allMarkets.getMarketData(marketId))._optionPrice[0] / 1, (Math.round(1.01 * 1e2) / 1e2) * 1e2); + // assert.equal((await allMarkets.getMarketData(marketId))._optionPrice[1] / 1, (Math.round(1.89 * 1e2) / 1e2) * 1e2); + // assert.equal((await allMarkets.getMarketData(marketId))._optionPrice[2] / 1, (Math.round(1.08 * 1e2) / 1e2) * 1e2); + // }); + }); +}); diff --git a/test/plotusWithBlotMetaTx.test.js b/test/plotusWithBlotMetaTx.test.js new file mode 100644 index 000000000..f925c127f --- /dev/null +++ b/test/plotusWithBlotMetaTx.test.js @@ -0,0 +1,210 @@ +const { assert } = require("chai"); +const OwnedUpgradeabilityProxy = artifacts.require("OwnedUpgradeabilityProxy"); +const Master = artifacts.require("Master"); +const MemberRoles = artifacts.require("MemberRoles"); +const PlotusToken = artifacts.require("MockPLOT"); +const MarketUtility = artifacts.require("MockConfig"); //mock +const MockConfig = artifacts.require("MockConfig"); +const Governance = artifacts.require("Governance"); +const AllMarkets = artifacts.require("MockAllMarkets"); +const BLOT = artifacts.require("BLOT"); +const MarketCreationRewards = artifacts.require('MarketCreationRewards'); +const TokenController = artifacts.require("MockTokenController"); +const MockChainLinkAggregator = artifacts.require("MockChainLinkAggregator"); +const BigNumber = require("bignumber.js"); + +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 encode3 = require("./utils/encoder.js").encode3; +const signAndExecuteMetaTx = require("./utils/signAndExecuteMetaTx.js").signAndExecuteMetaTx; +const BN = require('bn.js'); + +const gvProposal = require("./utils/gvProposal.js").gvProposalWithIncentiveViaTokenHolder; +const { toHex, toWei, toChecksumAddress } = require("./utils/ethTools"); +const to8Power = (number) => String(parseFloat(number) * 1e8); +let pkList = ["fb437e3e01939d9d4fef43138249f23dc1d0852e69b0b5d1647c087f869fabbd","7c85a1f1da3120c941b83d71a154199ee763307683f206b98ad92c3b4e0af13e","ecc9b35bf13bd5459350da564646d05c5664a7476fe5acdf1305440f88ed784c","f4470c3fca4dbef1b2488d016fae25978effc586a1f83cb29ac8cb6ab5bc2d50","141319b1a84827e1046e93741bf8a9a15a916d49684ab04925ac4ce4573eea23","d54b606094287758dcf19064a8d91c727346aadaa9388732e73c4315b7c606f9","49030e42ce4152e715a7ddaa10e592f8e61d00f70ef11f48546711f159d985df","b96761b1e7ebd1e8464a78a98fe52f53ce6035c32b4b2b12307a629a551ff7cf","d4786e2581571c863c7d12231c3afb6d4cef390c0ac9a24b243293721d28ea95","ed28e3d3530544f1cf2b43d1956b7bd13b63c612d963a8fb37387aa1a5e11460","05b127365cf115d4978a7997ee98f9b48f0ddc552b981c18aa2ee1b3e6df42c6","9d11dd6843f298b01b34bd7f7e4b1037489871531d14b58199b7cba1ac0841e6"]; +describe("newPlotusWithBlot", () => { + contract("AllMarket", async function (users) { + // Multiplier Sheet + let masterInstance, + plotusToken, + mockMarketConfig, + tokenControllerAdd, + tokenController, + plotusNewAddress, + plotusNewInstance, + governance, + allMarkets, + marketUtility, + mockChainLinkAggregator, + marketIncentives; + let predictionPointsBeforeUser1, predictionPointsBeforeUser2, predictionPointsBeforeUser3, predictionPointsBeforeUser4; + 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); + 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); + mockMarketConfig = await masterInstance.getLatestAddress(web3.utils.toHex("MU")); + mockMarketConfig = await MockConfig.at(mockMarketConfig); + allMarkets = await AllMarkets.at(await masterInstance.getLatestAddress(web3.utils.toHex("AM"))); + marketIncentives = await MarketCreationRewards.at(await masterInstance.getLatestAddress(web3.utils.toHex("MC"))); + await increaseTime(4 * 60 * 60 + 1); + await plotusToken.transfer(marketIncentives.address,toWei(100000)); + await allMarkets.createMarket(0, 0,{from: users[11]}); + // await marketIncentives.claimCreationReward(100,{from:users[11]}); + BLOTInstance = await BLOT.at(await masterInstance.getLatestAddress(web3.utils.toHex("BL"))); + }); + it("1. Place Prediction", async () => { + + let i; + let predictionVal = [0,100, 400, 210, 123, 200, 100, 300, 500, 200, 100]; + let options=[0,2,2,2,3,1,1,2,3,3,2]; + let withPlot = [0,true,false,true,false,false,true,false,false,true,true]; + + for(i=1;i<11;i++) { + let predictionToken; + let depositAmt; + if(withPlot[i]) + { + depositAmt = toWei(predictionVal[i]); + await plotusToken.transfer(users[i], toWei(predictionVal[i])); + await plotusToken.approve(allMarkets.address, toWei(predictionVal[i]), { from: users[i] }); + predictionToken = plotusToken.address; + + } else { + depositAmt=0; + await plotusToken.approve(BLOTInstance.address, toWei(predictionVal[i])); + await BLOTInstance.mint(users[i], toWei(predictionVal[i])); + predictionToken = BLOTInstance.address; + } + let functionSignature = encode3("depositAndPlacePrediction(uint,uint,address,uint64,uint256)",depositAmt , 7, predictionToken, to8Power(predictionVal[i]), options[i]); + await mockMarketConfig.setNextOptionPrice(options[i]*9); + await signAndExecuteMetaTx( + pkList[i], + users[i], + functionSignature, + allMarkets, + "AM" + ); + } + }); + it("1.2 Relayer should get apt reward", async () => { + + let relayerBalBefore = await plotusToken.balanceOf(users[0]); + await allMarkets.claimRelayerRewards(); + let relayerBalAfter = await plotusToken.balanceOf(users[0]); + + assert.equal(Math.round((relayerBalAfter-relayerBalBefore)/1e15),40.194*1e3); + }); + it("1.3 Check Prediction points allocated", async () => { + options = [0,2, 2, 2, 3, 1, 1, 2, 3, 3, 2]; + getPredictionPoints = async (user, option) => { + let predictionPoints = await allMarkets.getUserPredictionPoints(user, 7, option); + predictionPoints = predictionPoints / 1; + return predictionPoints; + }; + PredictionPointsExpected = [0,5444.44444, 21777.77777, 11433.33333, 4464.44444, 21777.77777, 10888.88888, 16333.33333, 18148.14815, 7259.25925, 5444.44444]; + + for (let index = 1; index < 11; index++) { + let PredictionPoints = await getPredictionPoints(users[index], options[index]); + PredictionPoints = PredictionPoints / 1e5; + try{ + assert.equal(PredictionPoints.toFixed(1), PredictionPointsExpected[index].toFixed(1)); + }catch(e){ + console.log(`Not equal!! -> Sheet: ${PredictionPointsExpected[index]} Got: ${PredictionPoints}`); + } + // commented by parv (as already added assert above) + // console.log(`Prediction points : ${PredictionPoints} expected : ${PredictionPointsExpected[index].toFixed(1)} `); + } + // console.log(await plotusToken.balanceOf(user1)); + + // close market + await increaseTime(8 * 60 * 60); + await allMarkets.postResultMock(1, 7); + await increaseTime(8 * 60 * 60); + }); + it("1.4 Check total return for each user Prediction values in plot", async () => { + options = [0,2, 2, 2, 3, 1, 1, 2, 3, 3, 2]; + getReturnsInPLOT = async (user) => { + const response = await allMarkets.getReturn(user, 7); + let returnAmountInPLOT = response / 1e8; + return returnAmountInPLOT; + }; + + const returnInPLOTExpected = [0,0,0,0,0,1452.578867,726.2894333,0,0,0,0]; + + for (let index = 1; index < 11; index++) { + let returns = await getReturnsInPLOT(users[index]) / 1; + try{ + assert.equal(returnInPLOTExpected[index].toFixed(2), returns.toFixed(2), ); + }catch(e){ + console.log(`Not equal!! -> Sheet: ${returnInPLOTExpected[index].toFixed(2)} Got: ${returns.toFixed(2)}`); + } + // commented by Parv (as assert already added above) + // console.log(`return : ${returns} Expected :${returnInPLOTExpected[index]}`); + } + }); + it("1.5 Check User Received The appropriate amount", async () => { + const totalReturnLotExpexted = [0,0,0,0,0,1452.578867,726.2894333,0,0,0,0];; + for (let i=1;i<11;i++) { + beforeClaimToken = await plotusToken.balanceOf(users[i]); + try { + let plotEthUnused = await allMarkets.getUserUnusedBalance(users[i]); + let functionSignature = encode3("withdraw(uint,uint)", plotEthUnused[0].iadd(plotEthUnused[1]), 10); + await signAndExecuteMetaTx( + pkList[i], + users[i], + functionSignature, + allMarkets, + "AM" + ); + } catch (e) { } + afterClaimToken = await plotusToken.balanceOf(users[i]); + conv = new BigNumber(1000000000000000000); + + diffToken = afterClaimToken - beforeClaimToken; + diffToken = diffToken / conv; + diffToken = diffToken.toFixed(2); + expectedInLot = totalReturnLotExpexted[i].toFixed(2); + + try{ + assert.equal(diffToken/1, expectedInLot); + }catch(e){ + console.log(`Not equal!! -> Sheet: ${expectedInLot} Got: ${diffToken}`); + } + // commented by Parv (as assert already added above) + // console.log(`User ${accounts.indexOf(account) + 1}`); + // console.log(`Returned in Eth : ${diff} Expected : ${expectedInEth} `); + // console.log(`Returned in Lot : ${diffToken} Expected : ${expectedInLot} `); + } + }); + it("1.6 Market creator should get apt reward", async () => { + let marketCreatorReward = await marketIncentives.getPendingMarketCreationRewards(users[11]); + assert.equal(94717000,Math.round(marketCreatorReward[1]/1e11)); + + let plotBalBeforeCreator = await plotusToken.balanceOf(users[11]); + + functionSignature = encode3("claimCreationReward(uint256)", 100); + await signAndExecuteMetaTx( + pkList[11], + users[11], + functionSignature, + marketIncentives, + "MC" + ); + + let plotBalAfterCreator = await plotusToken.balanceOf(users[11]); + + assert.equal(Math.round((plotBalAfterCreator-plotBalBeforeCreator)/1e11),94717000); + }); + }); +}); diff --git a/test/utils/encoder.js b/test/utils/encoder.js index b01d50b04..4ef71ee60 100644 --- a/test/utils/encoder.js +++ b/test/utils/encoder.js @@ -27,4 +27,10 @@ function encode1(...args) { return "0x" + encoded.toString("hex"); } -module.exports = { encode, encode1 }; +function encode3(...args) { + var encoded = abi.simpleEncode.apply(this, args); + encoded = encoded.toString('hex'); + return '0x' + encoded; +} + +module.exports = { encode, encode1, encode3}; diff --git a/test/utils/gvProposal.js b/test/utils/gvProposal.js index 6100ada3e..96161422c 100644 --- a/test/utils/gvProposal.js +++ b/test/utils/gvProposal.js @@ -1,8 +1,11 @@ const increaseTime = require("./increaseTime.js").increaseTime; const encode1 = require("./encoder.js").encode1; +const encode3 = require("./encoder.js").encode3; +const signAndExecuteMetaTx = require("./signAndExecuteMetaTx.js").signAndExecuteMetaTx; const Web3 = require("web3"); const { assert } = require("chai"); const web3 = new Web3(); +const privateKeyList = ["fb437e3e01939d9d4fef43138249f23dc1d0852e69b0b5d1647c087f869fabbd","7c85a1f1da3120c941b83d71a154199ee763307683f206b98ad92c3b4e0af13e","ecc9b35bf13bd5459350da564646d05c5664a7476fe5acdf1305440f88ed784c","f4470c3fca4dbef1b2488d016fae25978effc586a1f83cb29ac8cb6ab5bc2d50","141319b1a84827e1046e93741bf8a9a15a916d49684ab04925ac4ce4573eea23","d54b606094287758dcf19064a8d91c727346aadaa9388732e73c4315b7c606f9","49030e42ce4152e715a7ddaa10e592f8e61d00f70ef11f48546711f159d985df","b96761b1e7ebd1e8464a78a98fe52f53ce6035c32b4b2b12307a629a551ff7cf","d4786e2581571c863c7d12231c3afb6d4cef390c0ac9a24b243293721d28ea95","ed28e3d3530544f1cf2b43d1956b7bd13b63c612d963a8fb37387aa1a5e11460","05b127365cf115d4978a7997ee98f9b48f0ddc552b981c18aa2ee1b3e6df42c6","9d11dd6843f298b01b34bd7f7e4b1037489871531d14b58199b7cba1ac0841e6","f79e90fa4091de4fc2ec70f5bf67b24393285c112658e0d810e6bd711387fbb9","99f1fc0f09230ce745b6a256ba7082e6e51a2907abda3d9e735a5c8188bb4ba1","477f86cce983b9c91a36fdcd4a7ce21144a08dee9b1aafb91b9c70e57f717ce6","b03d2e6bb4a7d71c66a66ff9e9c93549cae4b593f634a4ea2a1f79f94200f5b4","9ddc0f53a81e631dcf39d5155f41ec12ed551b731efc3224f410667ba07b37dc","cf087ff9ae7c9954ad8612d071e5cdf34a6024ee1ae477217639e63a802a53dd","b64f62b94babb82cc78d3d1308631ae221552bb595202fc1d267e1c29ce7ba60","a91e24875f8a534497459e5ccb872c4438be3130d8d74b7e1104c5f94cdcf8c2","4f49f3d029eeeb3fed14d59625acd088b6b34f3b41c527afa09d29e4a7725c32","179795fd7ac7e7efcba3c36d539a1e8659fb40d77d0a3fab2c25562d99793086","4ba37d0b40b879eceaaca2802a1635f2e6d86d5c31e3ff2d2fd13e68dd2a6d3d","6b7f5dfba9cd3108f1410b56f6a84188eee23ab48a3621b209a67eea64293394","870c540da9fafde331a3316cee50c17ad76ddb9160b78b317bef2e6f6fc4bac0","470b4cccaea895d8a5820aed088357e380d66b8e7510f0a1ea9b575850160241","8a55f8942af0aec1e0df3ab328b974a7888ffd60ded48cc6862013da0f41afbc","2e51e8409f28baf93e665df2a9d646a1bf9ac8703cbf9a6766cfdefa249d5780","99ef1a23e95910287d39493d8d9d7d1f0b498286f2b1fdbc0b01495f10cf0958","6652200c53a4551efe2a7541072d817562812003f9d9ef0ec17995aa232378f8","39c6c01194df72dda97da2072335c38231ced9b39afa280452afcca901e73643","12097e411d948f77b7b6fa4656c6573481c1b4e2864c1fca9d5b296096707c45","cbe53bf1976aee6cec830a848c6ac132def1503cffde82ccfe5bd15e75cbaa72","eeab5dcfff92dbabb7e285445aba47bd5135a4a3502df59ac546847aeb5a964f","5ea8279a578027abefab9c17cef186cccf000306685e5f2ee78bdf62cae568dd","0607767d89ad9c7686dbb01b37248290b2fa7364b2bf37d86afd51b88756fe66","e4fd5f45c08b52dae40f4cdff45e8681e76b5af5761356c4caed4ca750dc65cd","145b1c82caa2a6d703108444a5cf03e9cb8c3cd3f19299582a564276dbbba734","736b22ec91ae9b4b2b15e8d8c220f6c152d4f2228f6d46c16e6a9b98b4733120","ac776cb8b40f92cdd307b16b83e18eeb1fbaa5b5d6bd992b3fda0b4d6de8524c","65ba30e2202fdf6f37da0f7cfe31dfb5308c9209885aaf4cef4d572fd14e2903","54e8389455ec2252de063e83d3ce72529d674e6d2dc2070661f01d4f76b63475","fbbbfb525dd0255ee332d51f59648265aaa20c2e9eff007765cf4d4a6940a849","8de5e418f34d04f6ea947ce31852092a24a705862e6b810ca9f83c2d5f9cda4d","ea6040989964f012fd3a92a3170891f5f155430b8bbfa4976cde8d11513b62d9","14d94547b5deca767137fbd14dae73e888f3516c742fad18b83be333b38f0b88","47f05203f6368d56158cda2e79167777fc9dcb0c671ef3aabc205a1636c26a29"]; async function gvProposal(...args) { let catId = args[0]; let actionHash = args[1]; @@ -74,13 +77,72 @@ async function gvProposalWithIncentiveViaTokenHolder(...args) { // for (iteration = 1; iteration < members[1].length; iteration++) await gv.submitVote(p, 1); + await increaseTime(604800); + if (seq != 3) await gv.closeProposal(p); + let proposal = await gv.proposal(p); + assert.equal(proposal[2].toNumber(), 3); +} + +async function gvProposalWithIncentiveViaTokenHolderMetaTX(...args) { + let catId = args[0]; + let actionHash = args[1]; + let mr = args[2]; + let gv = args[3]; + let seq = args[4]; + let incentive = args[5]; + let skipTrigger = args[6]; + let userAdd = args[7]; + let privateKey = args[8]; + let p = await gv.getProposalLength(); + let functionSignature = encode3("createProposal(string,string,string,uint256)","Proposal1", "Proposal1", "Proposal1", 0); + await signAndExecuteMetaTx( + privateKey, + userAdd, + functionSignature, + gv, + "GV" + ); + // await gv.createProposal("proposal", "proposal", "proposal", 0); + let canClose = await gv.canCloseProposal(p); + assert.equal(parseFloat(canClose),0); + functionSignature = encode3("categorizeProposal(uint256,uint256,uint256)",p, catId, incentive); + await signAndExecuteMetaTx( + privateKey, + userAdd, + functionSignature, + gv, + "GV" + ); + // await gv.categorizeProposal(p, catId, incentive); + functionSignature = encode3("submitProposalWithSolution(uint256,string,bytes)", p, "Addnewmember", actionHash); + await signAndExecuteMetaTx( + privateKey, + userAdd, + functionSignature, + gv, + "GV" + ); + // await gv.submitProposalWithSolution(p, "proposal", actionHash); + // let members = await mr.members(seq); + // let iteration = 0; + // for (iteration = 1; iteration < members[1].length; iteration++) + functionSignature = encode3("submitVote(uint256,uint256)",p, 1); + await signAndExecuteMetaTx( + privateKey, + userAdd, + functionSignature, + gv, + "GV" + ); + // await gv.submitVote(p, 1); + await increaseTime(604800); if (seq != 3) await gv.closeProposal(p); let proposal = await gv.proposal(p); assert.equal(proposal[2].toNumber(), 3); if(!skipTrigger) { await increaseTime(86401); - await gv.triggerAction(p); + // await gv.triggerAction(p); } } @@ -134,4 +196,5 @@ module.exports = { setTriggerActionTime, gvProposalWithoutTrigger, gvProposalWithIncentiveViaTokenHolder, + gvProposalWithIncentiveViaTokenHolderMetaTX }; \ No newline at end of file diff --git a/test/utils/signAndExecuteMetaTx.js b/test/utils/signAndExecuteMetaTx.js new file mode 100644 index 000000000..637872f87 --- /dev/null +++ b/test/utils/signAndExecuteMetaTx.js @@ -0,0 +1,58 @@ +var ethutil= require('ethereumjs-util'); +var abi = require('ethereumjs-abi'); +const BN = require('bn.js'); +var eip = require('eip-712'); + + +async function signAndExecuteMetaTx(...args) { + + let types = ['uint256', 'address', 'uint256', 'bytes']; + let pKey = args[0]; + let contractInstance = args[3]; + let functionSignature = args[2]; + let user = args[1]; + let contractName = args[4]; + var originalMessage1 = { + "types": { + "EIP712Domain": [ + { "name": "name", "type": "string" }, + { "name": "version", "type": "string" }, + { "name": "verifyingContract", "type": "address" }, + { "name": 'salt', "type": 'bytes32' } + ], + "MetaTransaction": [ + { "name": "nonce", "type": "uint256" }, + { "name": "from", "type": "address" }, + { "name": "functionSignature", "type": "bytes" }, + ] + }, + "primaryType": "MetaTransaction", + "domain": { + "name": contractName, + "version": await contractInstance.ERC712_VERSION(), + "salt": "0x0000000000000000000000000000000000000000000000000000000000000089",//await contractInstance.getChainId(), + "verifyingContract": contractInstance.address + }, + "message": { + "nonce" : await contractInstance.getNonce(user), + "from": user, + "functionSignature" : functionSignature + } + } + + let privateKey = Buffer.from(pKey, 'hex'); + + let signature = ethutil.ecsign(eip.getMessage(originalMessage1,true), privateKey); + let sign1 = []; + sign1[0]= signature.v ; + sign1[1]= '0x' + (signature.r).toString('hex'); + sign1[2]= '0x' + (signature.s).toString('hex'); + if(args[5]) + { + await contractInstance.executeMetaTransaction(user, functionSignature, sign1[1], sign1[2], sign1[0],{from:args[4]}); + } + else + await contractInstance.executeMetaTransaction(user, functionSignature, sign1[1], sign1[2], sign1[0]); +} + +module.exports = { signAndExecuteMetaTx }; \ No newline at end of file