├── scripts ├── coverage.sh ├── startGanache.sh ├── startGanache.bat └── test.sh ├── migrations ├── 1_initial_migration.js └── 2_deploy.js ├── contracts ├── interfaces │ ├── Iupgradable.sol │ ├── IbLOTToken.sol │ ├── IMaster.sol │ ├── IAllMarkets.sol │ ├── IMarketCreationRewards.sol │ ├── IChainLinkOracle.sol │ ├── ITokenController.sol │ ├── IToken.sol │ ├── IMarketRegistry.sol │ ├── IMarket.sol │ └── IMarketUtility.sol ├── mock │ ├── MockGovernance.sol │ ├── MockAllMarkets.sol │ ├── MockUniswapPair.sol │ ├── MockMarketRegistry.sol │ ├── MockPLOT.sol │ ├── MockUniswapFactory.sol │ ├── MockTokenController.sol │ ├── DummyMockMarket.sol │ ├── NewProxyInternalContract.sol │ ├── MockMemberRoles.sol │ ├── MockStaking.sol │ ├── MockMarket.sol │ ├── MockBTCMarket.sol │ ├── MockWeth.sol │ ├── MockUniswapRouter.sol │ ├── MockChainLinkAggregator.sol │ ├── MockChainLinkGasPriceAgg.sol │ ├── MockConfig.sol │ ├── DummyTokenMock2.sol │ ├── TokenMock.sol │ └── DummyTokenMock.sol ├── marketImplementations │ └── MarketBTC.sol ├── Migrations.sol ├── external │ ├── openzeppelin-solidity │ │ ├── math │ │ │ └── Math.sol │ │ ├── utils │ │ │ ├── Address.sol │ │ │ └── ReentrancyGuard.sol │ │ ├── access │ │ │ ├── Roles.sol │ │ │ └── roles │ │ │ │ └── MinterRole.sol │ │ ├── ownership │ │ │ └── Ownable.sol │ │ └── token │ │ │ └── ERC20 │ │ │ ├── IERC20.sol │ │ │ ├── SafeERC20.sol │ │ │ └── ERC20.sol │ ├── proxy │ │ ├── Proxy.sol │ │ ├── UpgradeabilityProxy.sol │ │ └── OwnedUpgradeabilityProxy.sol │ ├── uniswap │ │ ├── oracleLibrary.sol │ │ ├── FixedPoint.sol │ │ └── solidity-interface.sol │ ├── govblocks-protocol │ │ ├── Governed.sol │ │ └── interfaces │ │ │ ├── IMemberRoles.sol │ │ │ ├── IGovernance.sol │ │ │ └── IProposalCategory.sol │ └── lockable-token │ │ └── IERC1132.sol ├── TokenControllerV2.sol ├── MarketUtilityV2.sol ├── Airdrop.sol ├── PlotXToken.sol ├── Vesting.sol ├── Master.sol └── bLOTToken.sol ├── .gitignore ├── test ├── utils │ ├── web3.js │ ├── latestTime.js │ ├── assertRevert.js │ ├── snapshot.js │ ├── ethTools.js │ ├── expectEvent.js │ ├── encoder.js │ ├── advanceToBlock.js │ ├── helper.js │ ├── increaseTime.js │ └── gvProposal.js ├── utils.js ├── 22_blottoken.js ├── 23_cummulativePrices.test.js └── 08_MemberRoles.test.js ├── .solcover.js ├── .travis.yml ├── .github └── ISSUE_TEMPLATE │ ├── feature_request.md │ └── bug_report.md ├── package.json ├── UpgradeSteps.md ├── MajorFunctions.md ├── README.md └── truffle-config.js /scripts/coverage.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | SOLIDITY_COVERAGE=true scripts/test.sh 4 | -------------------------------------------------------------------------------- /migrations/1_initial_migration.js: -------------------------------------------------------------------------------- 1 | const Migrations = artifacts.require("Migrations"); 2 | 3 | module.exports = function(deployer) { 4 | deployer.deploy(Migrations); 5 | }; 6 | -------------------------------------------------------------------------------- /contracts/interfaces/Iupgradable.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.5.7; 2 | 3 | contract Iupgradable { 4 | 5 | /** 6 | * @dev change master address 7 | */ 8 | function setMasterAddress() public; 9 | } 10 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # build artifacts 2 | build 3 | coverage 4 | 5 | 6 | # dependencies 7 | /node_modules 8 | package-lock.json 9 | 10 | coverage.json 11 | todo.md 12 | tests 13 | .vscode/settings.json 14 | .solhint.json 15 | -------------------------------------------------------------------------------- /contracts/interfaces/IbLOTToken.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.5.7; 2 | 3 | contract IbLOTToken { 4 | function initiatebLOT(address _defaultMinter) external; 5 | function convertToPLOT(address _of, address _to, uint256 amount) public; 6 | } -------------------------------------------------------------------------------- /test/utils/web3.js: -------------------------------------------------------------------------------- 1 | const pify = require('pify'); 2 | 3 | const ethAsync = pify(web3.eth); 4 | 5 | module.exports = { 6 | ethGetBalance: ethAsync.getBalance, 7 | ethSendTransaction: ethAsync.sendTransaction, 8 | ethGetBlock: ethAsync.getBlock 9 | }; 10 | -------------------------------------------------------------------------------- /contracts/mock/MockGovernance.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.5.7; 2 | 3 | import "../Governance.sol"; 4 | 5 | contract MockGovernance is Governance { 6 | 7 | function _initiateGovernance() internal { 8 | super._initiateGovernance(); 9 | maxVoteWeigthPer = 50; 10 | } 11 | } -------------------------------------------------------------------------------- /contracts/mock/MockAllMarkets.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.5.7; 2 | 3 | import "../AllMarkets.sol"; 4 | 5 | contract MockAllMarkets is AllMarkets { 6 | 7 | function postResultMock(uint _val, uint _marketId) external { 8 | _postResult(_val, 0 , _marketId); 9 | } 10 | 11 | } -------------------------------------------------------------------------------- /contracts/mock/MockUniswapPair.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.5.7; 2 | 3 | 4 | contract MockUniswapPair { 5 | 6 | address public token0; 7 | address public token1; 8 | constructor(address _token0, address _token1) public { 9 | token0 = _token0; 10 | token1 = _token1; 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /contracts/mock/MockMarketRegistry.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.5.7; 2 | 3 | import "../MarketRegistry.sol"; 4 | 5 | contract MockMarketRegistry is MarketRegistry { 6 | 7 | function transferPlot(address payable _to, uint _amount) external { 8 | _transferAsset(address(plotToken), _to, _amount); 9 | } 10 | } -------------------------------------------------------------------------------- /test/utils/latestTime.js: -------------------------------------------------------------------------------- 1 | const { ethGetBlock } = require('./web3'); 2 | 3 | // Returns the time of the last mined block in seconds 4 | async function latestTime() { 5 | const block = await ethGetBlock('latest'); 6 | return block.timestamp; 7 | } 8 | 9 | module.exports = { 10 | latestTime 11 | }; 12 | -------------------------------------------------------------------------------- /scripts/startGanache.sh: -------------------------------------------------------------------------------- 1 | @echo off 2 | echo Loading Resources . . . 3 | cd ../node_modules/.bin/ 4 | echo starting ganache-cli . . . 5 | ./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 6 | ping 127.0.0.1 -n 5 > nul 7 | -------------------------------------------------------------------------------- /contracts/marketImplementations/MarketBTC.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.5.7; 2 | 3 | import "../Market.sol"; 4 | contract MarketBTC is Market { 5 | 6 | bool constant isChainlinkFeed = true; 7 | address constant marketFeedAddress = 0x5e2aa6b66531142bEAB830c385646F97fa03D80a; 8 | bytes32 public constant marketCurrency = "BTC/USDT"; 9 | 10 | } 11 | -------------------------------------------------------------------------------- /contracts/mock/MockPLOT.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.5.7; 2 | import "../PlotXToken.sol"; 3 | 4 | contract MockPLOT is PlotXToken { 5 | 6 | constructor(uint256 initialSupply, address owner) public PlotXToken(initialSupply, owner) { 7 | } 8 | 9 | function burnTokens(address _of, uint _amount) external { 10 | _burn(_of, _amount); 11 | } 12 | } -------------------------------------------------------------------------------- /contracts/interfaces/IMaster.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.5.7; 2 | 3 | contract IMaster { 4 | function dAppToken() public view returns(address); 5 | function isInternal(address _address) public view returns(bool); 6 | function getLatestAddress(bytes2 _module) public view returns(address); 7 | function isAuthorizedToGovern(address _toCheck) public view returns(bool); 8 | } -------------------------------------------------------------------------------- /scripts/startGanache.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | echo Loading Resources . . . 3 | cd ../node_modules/.bin/ 4 | echo starting ganche-cli . . . 5 | 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" 6 | ping 127.0.0.1 -n 5 > nul 7 | -------------------------------------------------------------------------------- /contracts/mock/MockUniswapFactory.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.5.7; 2 | 3 | 4 | contract MockUniswapFactory { 5 | 6 | address public plotETHPair; 7 | function getPair(address tokenA, address tokenB) external view returns (address pair) { 8 | return plotETHPair; 9 | } 10 | 11 | function setPair(address _plotETHPair) public { 12 | plotETHPair = _plotETHPair; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /.solcover.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | skipFiles: ['external', 'mock', 'interfaces', 'marketImplementations'], 3 | providerOptions: { 4 | default_balance_ether: 250, // Extra zero, coverage consumes more gas 5 | network_id: 5777, 6 | mnemonic: 7 | 'grocery obvious wire insane limit weather parade parrot patrol stock blast ivory', 8 | total_accounts: 47, 9 | hardfork: 'constantinople' 10 | } 11 | }; 12 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | dist: trusty 2 | sudo: required 3 | language: node_js 4 | 5 | node_js: 6 | - "12" 7 | 8 | jobs: 9 | fast_finish: true 10 | allow_failures: 11 | - env: SOLIDITY_COVERAGE=true 12 | include: 13 | - stage: tests 14 | name: "unit tests" 15 | script: npm run test 16 | - stage: tests 17 | name: "unit tests with coverage" 18 | script: npm run test 19 | env: SOLIDITY_COVERAGE=true -------------------------------------------------------------------------------- /test/utils/assertRevert.js: -------------------------------------------------------------------------------- 1 | async function assertRevert(promise) { 2 | try { 3 | await promise; 4 | throw null; 5 | } catch (error) { 6 | assert(error, `Expected an error but did not get one`); 7 | assert( 8 | error.message.includes('revert'), 9 | `Expected an error containing "revert" but got "${error.message}" instead` 10 | ); 11 | } 12 | } 13 | 14 | module.exports = { 15 | assertRevert 16 | }; 17 | -------------------------------------------------------------------------------- /test/utils/snapshot.js: -------------------------------------------------------------------------------- 1 | 2 | const send = (method, params = []) => new Promise((resolve, reject) => { 3 | web3.currentProvider.send( 4 | { jsonrpc: '2.0', id: Date.now(), method, params }, 5 | (err, res) => err ? reject(err) : resolve(res), 6 | ); 7 | }); 8 | 9 | const takeSnapshot = async () => send('evm_snapshot'); 10 | const revertSnapshot = async id => send('evm_revert', [id]); 11 | 12 | module.exports = { 13 | takeSnapshot, 14 | revertSnapshot, 15 | }; -------------------------------------------------------------------------------- /test/utils/ethTools.js: -------------------------------------------------------------------------------- 1 | const Web3 = require('web3'); 2 | const web3 = new Web3(new Web3.providers.HttpProvider('http://localhost:8545')); // Hardcoded development port 3 | function ether(n) { 4 | return new web3.BigNumber(web3.toWei(n, 'ether')); 5 | } 6 | 7 | function toWei(value) { 8 | return web3.toWei(value, 'ether'); 9 | } 10 | 11 | function toHex(value) { 12 | return web3.toHex(value); 13 | } 14 | module.exports = { 15 | ether, 16 | toWei, 17 | toHex 18 | }; 19 | -------------------------------------------------------------------------------- /contracts/interfaces/IAllMarkets.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.5.7; 2 | 3 | contract IAllMarkets { 4 | 5 | enum PredictionStatus { 6 | Live, 7 | InSettlement, 8 | Cooling, 9 | InDispute, 10 | Settled 11 | } 12 | 13 | function marketStatus(uint256 _marketId) public view returns(PredictionStatus); 14 | 15 | function burnDisputedProposalTokens(uint _proposaId) external; 16 | 17 | function getTotalStakedValueInPLOT(uint256 _marketId) public view returns(uint256); 18 | 19 | } 20 | -------------------------------------------------------------------------------- /test/utils/expectEvent.js: -------------------------------------------------------------------------------- 1 | const should = require('chai').should(); 2 | 3 | function inLogs(logs, eventName, eventArgs = {}) { 4 | const event = logs.find(e => e.event === eventName); 5 | should.exist(event); 6 | for (const [k, v] of Object.entries(eventArgs)) { 7 | should.exist(event.args[k]); 8 | event.args[k].should.equal(v); 9 | } 10 | return event; 11 | } 12 | 13 | async function inTransaction(tx, eventName, eventArgs = {}) { 14 | const { logs } = await tx; 15 | return inLogs(logs, eventName, eventArgs); 16 | } 17 | 18 | module.exports = { 19 | inLogs, 20 | inTransaction 21 | }; 22 | -------------------------------------------------------------------------------- /contracts/mock/MockTokenController.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.5.7; 2 | 3 | import "../TokenController.sol"; 4 | 5 | contract MockTokenController is TokenController { 6 | 7 | uint public bit; 8 | 9 | /** 10 | * @dev to change the operator address 11 | * @param _newOperator is the new address of operator 12 | */ 13 | function changeOperator(address _newOperator) public { 14 | token.changeOperator(_newOperator); 15 | } 16 | 17 | function dummyOnlyInternalFunction(uint _val) public { 18 | require(IMaster(masterAddress).isInternal(msg.sender)); 19 | bit = _val; 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /contracts/Migrations.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.4.21 <0.7.0; 2 | 3 | contract Migrations { 4 | address public owner; 5 | uint public last_completed_migration; 6 | 7 | constructor() public { 8 | owner = msg.sender; 9 | } 10 | 11 | /** 12 | * @dev Checks if msg.sender is not owner. 13 | */ 14 | modifier restricted() { 15 | if (msg.sender == owner) _; 16 | } 17 | 18 | /** 19 | * @dev Set the last completed migration. 20 | * @param completed The last completed migration. 21 | */ 22 | function setCompleted(uint completed) public restricted { 23 | last_completed_migration = completed; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /contracts/mock/DummyMockMarket.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.5.7; 2 | 3 | import "../Market.sol"; 4 | 5 | contract DummyMockMarket is Market { 6 | 7 | mapping(uint => uint) optionPrices; 8 | 9 | bool public mockFlag; 10 | 11 | function setMockPriceFlag(bool _flag) public { 12 | mockFlag = _flag; 13 | } 14 | 15 | function dummyFunction() public view returns(uint) 16 | { 17 | 18 | return 123; 19 | } 20 | 21 | /** 22 | * @dev Calculate the result of market. 23 | * @param _value The current price of market currency. 24 | */ 25 | function calculatePredictionResult(uint _value) public { 26 | _postResult(_value, 0); 27 | } 28 | } -------------------------------------------------------------------------------- /contracts/mock/NewProxyInternalContract.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.5.7; 2 | 3 | import "../Master.sol"; 4 | import "../interfaces/Iupgradable.sol"; 5 | import "./MockTokenController.sol"; 6 | 7 | contract NewProxyInternalContract is Iupgradable { 8 | MockTokenController tc; 9 | Master public ms; 10 | 11 | function setMasterAddress() public { 12 | ms = Master(msg.sender); 13 | } 14 | 15 | function callDummyOnlyInternalFunction(uint _val) public { 16 | tc = MockTokenController(ms.getLatestAddress('TC')); 17 | tc.dummyOnlyInternalFunction(_val); 18 | } 19 | 20 | function changeDependentContractAddress() public { 21 | require(ms.isInternal(msg.sender)); 22 | } 23 | } -------------------------------------------------------------------------------- /contracts/interfaces/IMarketCreationRewards.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.5.7; 2 | 3 | contract IMarketCreationRewards { 4 | 5 | function calculateMarketCreationIncentive(address _createdBy, uint256 _gasCosumed, uint64 _marketId) external; 6 | 7 | function depositMarketRewardPoolShare(uint256 _marketId, uint256 _ethShare, uint256 _plotShare, uint64 _ethDeposit, uint64 _plotDeposit) external payable; 8 | 9 | function returnMarketRewardPoolShare(uint256 _marketId) external; 10 | 11 | function getMarketCreatorRPoolShareParams(uint256 _market, uint256 plotStaked, uint256 ethStaked) external view returns(uint16, bool); 12 | 13 | function transferAssets(address _asset, address _to, uint _amount) external; 14 | 15 | } 16 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: Short Description of Feature 5 | labels: enhancement 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /test/utils/encoder.js: -------------------------------------------------------------------------------- 1 | const abi = require("ethereumjs-abi"); 2 | const Web3 = require("web3"); 3 | const { toHex } = require("./ethTools.js"); 4 | 5 | function encode(...args) { 6 | if (args.length === 1) { 7 | return "0x"; 8 | } 9 | 10 | const [fn, ...params] = args; 11 | const types = fn 12 | .slice(0, fn.length - 1) 13 | .split("(")[1] 14 | .split(","); 15 | 16 | for (let i = 0; i < types.length; i++) { 17 | if (types[i].includes("bytes") && !params[i].startsWith("0x")) { 18 | params[i] = toHex(params[i]); 19 | } 20 | } 21 | 22 | return encode1(types, params); 23 | } 24 | 25 | function encode1(...args) { 26 | const encoded = abi.rawEncode.apply(this, args); 27 | return "0x" + encoded.toString("hex"); 28 | } 29 | 30 | module.exports = { encode, encode1 }; 31 | -------------------------------------------------------------------------------- /contracts/mock/MockMemberRoles.sol: -------------------------------------------------------------------------------- 1 | import "../MemberRoles.sol"; 2 | contract MockMemberRoles is MemberRoles { 3 | /** 4 | * @dev is used to add initial advisory board members 5 | * @param abArray is the list of initial advisory board members 6 | */ 7 | function addInitialABMembers( 8 | address[] calldata abArray 9 | ) external { 10 | require( 11 | numberOfMembers(uint256(Role.AdvisoryBoard)) == 1, 12 | "Already initialized!" 13 | ); 14 | 15 | for (uint256 i = 0; i < abArray.length; i++) { 16 | require( 17 | checkRole(abArray[i], uint256(Role.TokenHolder)), 18 | "not a token holder" 19 | ); 20 | 21 | _updateRole(abArray[i], uint256(Role.AdvisoryBoard), true); 22 | } 23 | } 24 | 25 | } -------------------------------------------------------------------------------- /contracts/interfaces/IChainLinkOracle.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.5.7; 2 | 3 | interface IChainLinkOracle 4 | { 5 | /** 6 | * @dev Gets the latest answer of chainLink oracle. 7 | * @return int256 representing the latest answer of chainLink oracle. 8 | */ 9 | function latestAnswer() external view returns (int256); 10 | function decimals() external view returns (uint8); 11 | function getRoundData(uint80 _roundId) 12 | external 13 | view 14 | returns ( 15 | uint80 roundId, 16 | int256 answer, 17 | uint256 startedAt, 18 | uint256 updatedAt, 19 | uint80 answeredInRound 20 | ); 21 | 22 | function latestRoundData() 23 | external 24 | view 25 | returns ( 26 | uint80 roundId, 27 | int256 answer, 28 | uint256 startedAt, 29 | uint256 updatedAt, 30 | uint80 answeredInRound 31 | ); 32 | } -------------------------------------------------------------------------------- /test/utils/advanceToBlock.js: -------------------------------------------------------------------------------- 1 | function advanceBlock() { 2 | return new Promise((resolve, reject) => { 3 | web3.currentProvider.send( 4 | { 5 | jsonrpc: '2.0', 6 | method: 'evm_mine', 7 | id: Date.now() 8 | }, 9 | (err, res) => { 10 | return err ? reject(err) : resolve(res); 11 | } 12 | ); 13 | }); 14 | } 15 | 16 | // Advances the block number so that the last mined block is `number`. 17 | async function advanceToBlock(number) { 18 | if (web3.eth.blockNumber > number) { 19 | throw Error( 20 | `block number ${number} is in the past (current is ${ 21 | web3.eth.blockNumber 22 | })` 23 | ); 24 | } 25 | console.log("lol=> ", web3.eth.blockNumber); 26 | while (web3.eth.blockNumber < number) { 27 | await advanceBlock(); 28 | } 29 | } 30 | 31 | module.exports = { 32 | advanceBlock, 33 | advanceToBlock 34 | }; 35 | -------------------------------------------------------------------------------- /contracts/external/openzeppelin-solidity/math/Math.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.0; 2 | 3 | /** 4 | * @dev Standard math utilities missing in the Solidity language. 5 | */ 6 | library Math { 7 | /** 8 | * @dev Returns the largest of two numbers. 9 | */ 10 | function max(uint256 a, uint256 b) internal pure returns (uint256) { 11 | return a >= b ? a : b; 12 | } 13 | 14 | /** 15 | * @dev Returns the smallest of two numbers. 16 | */ 17 | function min(uint256 a, uint256 b) internal pure returns (uint256) { 18 | return a < b ? a : b; 19 | } 20 | 21 | /** 22 | * @dev Returns the average of two numbers. The result is rounded towards 23 | * zero. 24 | */ 25 | function average(uint256 a, uint256 b) internal pure returns (uint256) { 26 | // (a + b) / 2 can overflow, so we distribute 27 | return (a / 2) + (b / 2) + ((a % 2 + b % 2) / 2); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /contracts/mock/MockStaking.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.5.7; 2 | 3 | import "../Staking.sol"; 4 | 5 | contract MockStaking is Staking { 6 | 7 | constructor(address _stakeToken, address _rewardToken, uint256 stakingPeriod, uint256 _totalRewardToBeDistributed, uint256 startTime, address vaultAdd) public Staking(_stakeToken, _rewardToken, stakingPeriod, _totalRewardToBeDistributed, startTime, vaultAdd) { 8 | } 9 | 10 | function setBuyInRate(address _user, uint _value) public 11 | { 12 | interestData.stakers[_user].stakeBuyinRate = _value; 13 | } 14 | 15 | function addStake(address _user, uint _value) public 16 | { 17 | interestData.stakers[_user].totalStaked = _value; 18 | } 19 | 20 | function setInterestData(uint a, uint b) public { 21 | interestData.globalTotalStaked = a; 22 | interestData.globalYieldPerToken = b; 23 | } 24 | 25 | function setStarttime() public { 26 | stakingStartTime = now; 27 | } 28 | 29 | } -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: "[Short description of bug]" 5 | labels: bug 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Desktop (please complete the following information):** 27 | - Browser [e.g. chrome, safari] 28 | - Extension 29 | 30 | **Smartphone (please complete the following information):** 31 | - Browser [e.g. stock browser, safari] 32 | - Extension 33 | 34 | **Additional context** 35 | Add any other context about the problem here. 36 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "plotussc", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "directories": { 7 | "test": "test" 8 | }, 9 | "scripts": { 10 | "compile": "node_modules/.bin/truffle compile", 11 | "startGanache": ". scripts/startGanache.sh", 12 | "deploy": "node_modules/.bin/truffle deploy", 13 | "test": "./scripts/test.sh", 14 | "coverage": "./scripts/coverage.sh" 15 | }, 16 | "author": "", 17 | "license": "ISC", 18 | "dependencies": { 19 | "@openzeppelin/contracts": "2.5.0", 20 | "@openzeppelin/test-helpers": "0.5.6", 21 | "bignumber.js": "9.0.0", 22 | "coveralls": "3.0.2", 23 | "ethereumjs-abi": "0.6.8", 24 | "ganache-cli": "6.9.0", 25 | "pify": "5.0.0", 26 | "solhint": "3.2.0", 27 | "solidity-coverage": "0.7.1", 28 | "truffle": "5.1.19", 29 | "truffle-contract-size": "2.0.1", 30 | "web3": "0.20.4" 31 | }, 32 | "devDependencies": { 33 | "chai": "4.2.0" 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /contracts/TokenControllerV2.sol: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2020 PlotX.io 2 | 3 | This program is free software: you can redistribute it and/or modify 4 | it under the terms of the GNU General Public License as published by 5 | the Free Software Foundation, either version 3 of the License, or 6 | (at your option) any later version. 7 | 8 | This program is distributed in the hope that it will be useful, 9 | but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | GNU General Public License for more details. 12 | 13 | You should have received a copy of the GNU General Public License 14 | along with this program. If not, see http://www.gnu.org/licenses/ */ 15 | 16 | pragma solidity 0.5.7; 17 | 18 | import "./TokenController.sol"; 19 | 20 | contract TokenControllerV2 is TokenController { 21 | 22 | modifier onlyAuthorized { 23 | require(marketRegistry.isMarket(msg.sender) || IMaster(masterAddress).isInternal(msg.sender), "Not authorized"); 24 | _; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /contracts/external/openzeppelin-solidity/utils/Address.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.0; 2 | 3 | /** 4 | * @dev Collection of functions related to the address type, 5 | */ 6 | library Address { 7 | /** 8 | * @dev Returns true if `account` is a contract. 9 | * 10 | * This test is non-exhaustive, and there may be false-negatives: during the 11 | * execution of a contract's constructor, its address will be reported as 12 | * not containing a contract. 13 | * 14 | * > It is unsafe to assume that an address for which this function returns 15 | * false is an externally-owned account (EOA) and not a contract. 16 | */ 17 | function isContract(address account) internal view returns (bool) { 18 | // This method relies in extcodesize, which returns 0 for contracts in 19 | // construction, since the code is only stored at the end of the 20 | // constructor execution. 21 | 22 | uint256 size; 23 | // solhint-disable-next-line no-inline-assembly 24 | assembly { size := extcodesize(account) } 25 | return size > 0; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /contracts/external/openzeppelin-solidity/access/Roles.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.0; 2 | 3 | /** 4 | * @title Roles 5 | * @dev Library for managing addresses assigned to a Role. 6 | */ 7 | library Roles { 8 | struct Role { 9 | mapping (address => bool) bearer; 10 | } 11 | 12 | /** 13 | * @dev Give an account access to this role. 14 | */ 15 | function add(Role storage role, address account) internal { 16 | require(!has(role, account), "Roles: account already has role"); 17 | role.bearer[account] = true; 18 | } 19 | 20 | /** 21 | * @dev Remove an account's access to this role. 22 | */ 23 | function remove(Role storage role, address account) internal { 24 | require(has(role, account), "Roles: account does not have role"); 25 | role.bearer[account] = false; 26 | } 27 | 28 | /** 29 | * @dev Check if an account has this role. 30 | * @return bool 31 | */ 32 | function has(Role storage role, address account) internal view returns (bool) { 33 | require(account != address(0), "Roles: account is the zero address"); 34 | return role.bearer[account]; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /contracts/external/openzeppelin-solidity/access/roles/MinterRole.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.0; 2 | 3 | import "../Roles.sol"; 4 | 5 | contract MinterRole { 6 | using Roles for Roles.Role; 7 | 8 | event MinterAdded(address indexed account); 9 | event MinterRemoved(address indexed account); 10 | 11 | Roles.Role private _minters; 12 | 13 | constructor () internal { 14 | _addMinter(msg.sender); 15 | } 16 | 17 | modifier onlyMinter() { 18 | require(isMinter(msg.sender), "MinterRole: caller does not have the Minter role"); 19 | _; 20 | } 21 | 22 | function isMinter(address account) public view returns (bool) { 23 | return _minters.has(account); 24 | } 25 | 26 | function addMinter(address account) public onlyMinter { 27 | _addMinter(account); 28 | } 29 | 30 | function renounceMinter() public { 31 | _removeMinter(msg.sender); 32 | } 33 | 34 | function _addMinter(address account) internal { 35 | _minters.add(account); 36 | emit MinterAdded(account); 37 | } 38 | 39 | function _removeMinter(address account) internal { 40 | _minters.remove(account); 41 | emit MinterRemoved(account); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /contracts/external/proxy/Proxy.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.5.7; 2 | 3 | 4 | /** 5 | * @title Proxy 6 | * @dev Gives the possibility to delegate any call to a foreign implementation. 7 | */ 8 | contract Proxy { 9 | /** 10 | * @dev Fallback function allowing to perform a delegatecall to the given implementation. 11 | * This function will return whatever the implementation call returns 12 | */ 13 | function () external payable { 14 | address _impl = implementation(); 15 | require(_impl != address(0)); 16 | 17 | assembly { 18 | let ptr := mload(0x40) 19 | calldatacopy(ptr, 0, calldatasize) 20 | let result := delegatecall(gas, _impl, ptr, calldatasize, 0, 0) 21 | let size := returndatasize 22 | returndatacopy(ptr, 0, size) 23 | 24 | switch result 25 | case 0 { revert(ptr, size) } 26 | default { return(ptr, size) } 27 | } 28 | } 29 | 30 | /** 31 | * @dev Tells the address of the implementation where every call will be delegated. 32 | * @return address of the implementation to which it will be delegated 33 | */ 34 | function implementation() public view returns (address); 35 | } -------------------------------------------------------------------------------- /contracts/mock/MockMarket.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.5.7; 2 | 3 | import "../Market.sol"; 4 | 5 | contract MockMarket is Market { 6 | 7 | mapping(uint => uint) optionPrices; 8 | 9 | bool public mockFlag; 10 | 11 | function setMockPriceFlag(bool _flag) public { 12 | mockFlag = _flag; 13 | } 14 | 15 | function setOptionRangesPublic(uint _midRangeMin, uint _midRangeMax) public{ 16 | marketData.neutralMinValue = uint64(_midRangeMin*1e8); 17 | marketData.neutralMaxValue = uint64(_midRangeMax*1e8); 18 | // optionsAvailable[1].minValue = 0; 19 | // optionsAvailable[1].maxValue = _midRangeMin.sub(1); 20 | // optionsAvailable[2].minValue = _midRangeMin; 21 | // optionsAvailable[2].maxValue = _midRangeMax; 22 | // optionsAvailable[3].minValue = _midRangeMax.add(1); 23 | // optionsAvailable[3].maxValue = ~uint256(0) ; 24 | } 25 | 26 | function initiate(uint64 _startTime, uint64 _predictionTime, uint64 _minValue, uint64 _maxValue) public payable { 27 | mockFlag = true; 28 | super.initiate(_startTime, _predictionTime, _minValue, _maxValue); 29 | } 30 | 31 | /** 32 | * @dev Calculate the result of market. 33 | * @param _value The current price of market currency. 34 | */ 35 | function calculatePredictionResult(uint _value) public { 36 | _postResult(_value, 0); 37 | } 38 | 39 | function setOptionPrice(uint _option, uint _price) public { 40 | optionPrices[_option] = _price; 41 | } 42 | 43 | } -------------------------------------------------------------------------------- /contracts/mock/MockBTCMarket.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.5.7; 2 | 3 | import "../marketImplementations/MarketBTC.sol"; 4 | 5 | contract MockBTCMarket is MarketBTC { 6 | 7 | mapping(uint => uint) optionPrices; 8 | 9 | bool public mockFlag; 10 | 11 | function setMockPriceFlag(bool _flag) public { 12 | mockFlag = _flag; 13 | } 14 | 15 | function setOptionRangesPublic(uint _midRangeMin, uint _midRangeMax) public{ 16 | marketData.neutralMinValue = uint64(_midRangeMin*1e8); 17 | marketData.neutralMaxValue = uint64(_midRangeMax*1e8); 18 | // optionsAvailable[1].minValue = 0; 19 | // optionsAvailable[1].maxValue = _midRangeMin.sub(1); 20 | // optionsAvailable[2].minValue = _midRangeMin; 21 | // optionsAvailable[2].maxValue = _midRangeMax; 22 | // optionsAvailable[3].minValue = _midRangeMax.add(1); 23 | // optionsAvailable[3].maxValue = ~uint256(0) ; 24 | } 25 | 26 | function initiate(uint64 _startTime, uint64 _predictionTime, uint64 _minValue, uint64 _maxValue) public payable { 27 | mockFlag = true; 28 | super.initiate(_startTime, _predictionTime, _minValue, _maxValue); 29 | } 30 | 31 | /** 32 | * @dev Calculate the result of market. 33 | * @param _value The current price of market currency. 34 | */ 35 | function calculatePredictionResult(uint _value) public { 36 | _postResult(_value, 0); 37 | } 38 | 39 | function setOptionPrice(uint _option, uint _price) public { 40 | optionPrices[_option] = _price; 41 | } 42 | 43 | } -------------------------------------------------------------------------------- /contracts/interfaces/ITokenController.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.5.7; 2 | 3 | contract ITokenController { 4 | address public token; 5 | address public bLOTToken; 6 | 7 | /** 8 | * @dev Swap BLOT token. 9 | * account. 10 | * @param amount The amount that will be swapped. 11 | */ 12 | function swapBLOT(address _of, address _to, uint256 amount) public; 13 | 14 | function totalBalanceOf(address _of) 15 | public 16 | view 17 | returns (uint256 amount); 18 | 19 | function transferFrom(address _token, address _of, address _to, uint256 amount) public; 20 | 21 | /** 22 | * @dev Returns tokens locked for a specified address for a 23 | * specified reason at a specific time 24 | * @param _of The address whose tokens are locked 25 | * @param _reason The reason to query the lock tokens for 26 | * @param _time The timestamp to query the lock tokens for 27 | */ 28 | function tokensLockedAtTime(address _of, bytes32 _reason, uint256 _time) 29 | public 30 | view 31 | returns (uint256 amount); 32 | 33 | /** 34 | * @dev burns an amount of the tokens of the message sender 35 | * account. 36 | * @param amount The amount that will be burnt. 37 | */ 38 | function burnCommissionTokens(uint256 amount) external returns(bool); 39 | 40 | function initiateVesting(address _vesting) external; 41 | 42 | function lockForGovernanceVote(address _of, uint _days) public; 43 | 44 | function totalSupply() public view returns (uint256); 45 | 46 | function mint(address _member, uint _amount) public; 47 | 48 | } -------------------------------------------------------------------------------- /contracts/mock/MockWeth.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.5.7; 2 | 3 | 4 | contract MockWeth { 5 | string public name = "Wrapped Ether"; 6 | string public symbol = "WETH"; 7 | uint8 public decimals = 18; 8 | 9 | mapping (address => uint) public balanceOf; 10 | mapping (address => mapping (address => uint)) public allowance; 11 | 12 | function() external payable { 13 | deposit(); 14 | } 15 | function deposit() public payable { 16 | balanceOf[msg.sender] += msg.value; 17 | } 18 | function withdraw(uint wad) public { 19 | require(balanceOf[msg.sender] >= wad); 20 | balanceOf[msg.sender] -= wad; 21 | msg.sender.transfer(wad); 22 | } 23 | 24 | function totalSupply() public view returns (uint) { 25 | return address(this).balance; 26 | } 27 | 28 | function approve(address guy, uint wad) public returns (bool) { 29 | allowance[msg.sender][guy] = wad; 30 | return true; 31 | } 32 | 33 | function transfer(address dst, uint wad) public returns (bool) { 34 | return transferFrom(msg.sender, dst, wad); 35 | } 36 | 37 | function transferFrom(address src, address dst, uint wad) 38 | public 39 | returns (bool) 40 | { 41 | require(balanceOf[src] >= wad); 42 | 43 | if (src != msg.sender && allowance[src][msg.sender] != uint(-1)) { 44 | require(allowance[src][msg.sender] >= wad); 45 | allowance[src][msg.sender] -= wad; 46 | } 47 | 48 | balanceOf[src] -= wad; 49 | balanceOf[dst] += wad; 50 | 51 | return true; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /scripts/test.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Exit script as soon as a command fails. 4 | set -o errexit 5 | 6 | # Executes cleanup function at script exit. 7 | trap cleanup EXIT 8 | 9 | cleanup() { 10 | # Kill the ganache instance that we started (if we started one and if it's still running). 11 | if [ -n "$ganache_pid" ] && ps -p $ganache_pid > /dev/null; then 12 | kill -9 $ganache_pid 13 | fi 14 | } 15 | 16 | ganache_port=7545 17 | 18 | ganache_running() { 19 | nc -z localhost "$ganache_port" 20 | } 21 | 22 | start_ganache() { 23 | 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 & 24 | ganache_pid=$! 25 | } 26 | 27 | if ganache_running; then 28 | echo "Using existing ganache instance" 29 | else 30 | echo "Starting our own ganache instance" 31 | start_ganache 32 | sleep 2 33 | fi 34 | 35 | if [ -d "node_modules/eth-lightwallet/node_modules/bitcore-lib" ]; then 36 | rm -r "node_modules/eth-lightwallet/node_modules/bitcore-lib" 37 | echo "Deleted eth bitcore-lib" 38 | fi 39 | if [ -d "node_modules/bitcore-mnemonic/node_modules/bitcore-lib" ]; then 40 | rm -r "node_modules/bitcore-mnemonic/node_modules/bitcore-lib" 41 | echo "Deleted mne bitcore-lib" 42 | fi 43 | 44 | if [ "$SOLIDITY_COVERAGE" = true ]; then 45 | npx truffle run coverage 46 | if [ "$CONTINUOUS_INTEGRATION" = true ]; then 47 | cat coverage/lcov.info | node_modules/.bin/coveralls 48 | fi 49 | else 50 | echo "Now let's test truffle" 51 | node_modules/.bin/truffle test "$@" 52 | fi -------------------------------------------------------------------------------- /contracts/mock/MockUniswapRouter.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.5.7; 2 | 3 | import "../external/uniswap/solidity-interface.sol"; 4 | import "../external/openzeppelin-solidity/math/SafeMath.sol"; 5 | import "../interfaces/IToken.sol"; 6 | 7 | contract MockUniswapRouter { 8 | 9 | using SafeMath for uint; 10 | 11 | uint public priceOfToken = 1e16; 12 | address token; 13 | 14 | constructor(address _token) public { 15 | token = _token; 16 | } 17 | 18 | function WETH() external pure returns (address) { 19 | return 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE; 20 | } 21 | 22 | function setPrice(uint _newPrice) external { 23 | priceOfToken = _newPrice; 24 | } 25 | 26 | 27 | function swapExactETHForTokens(uint amountOutMin, address[] calldata path, address to, uint deadline) 28 | external 29 | payable 30 | returns (uint[] memory amounts) { 31 | uint ethSent = msg.value; 32 | uint tokenOutput = ethSent.mul(1e18).div(priceOfToken); 33 | IToken(token).transfer(to, tokenOutput); 34 | amounts = new uint[](2); 35 | amounts[0] = ethSent; 36 | amounts[1] = tokenOutput; 37 | } 38 | 39 | function getAmountsOut(uint amountIn, address[] calldata path) external view returns (uint[] memory amounts) { 40 | amounts = new uint[](2); 41 | amounts[0] = amountIn; 42 | if(path[0] == 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) { 43 | amounts[1] = amountIn.mul(1e18).div(priceOfToken); 44 | } else { 45 | amounts[1] = amountIn.mul(priceOfToken).div(1e18); 46 | } 47 | } 48 | 49 | function () payable external { 50 | 51 | } 52 | 53 | 54 | } -------------------------------------------------------------------------------- /UpgradeSteps.md: -------------------------------------------------------------------------------- 1 | AllMarkets contract Upgarde steps 2 | - Deploy AllMarkets.sol 3 | - Deploy MarketCreationRewards.sol 4 | - Deploy GovernanceNew.sol 5 | - Deploy TokenControllerNew.sol 6 | - Deploy MarketUtilityNew.sol 7 | - Proposal of `category 9` to add new contract: Solution Parameters => [AllMarkets Address, "AM"] 8 | - Proposal of `category 9` to add new contract: Solution Parameters => [MarketCreationRewards address, "MC"] 9 | - Proposal of `category 7` to Upgrade multiple contract implementations: Solution Parameters => ["GV","TC"], [GovernanceNew, TokenControllerNew] 10 | - Proposal of `category 6` to Upgrade market utility contract implementation: Solution Parameters => [MarketUtility contract address, MarketUtilityNew(implementation address)] 11 | - Set authorized address in MarketUtility to AllMarkets: `setAuthorizedAddress()`, pass AllMarkets address as argument 12 | - Initialise the MarketCreationRewards contract=> `MarketCreationRewards.initialise()` pass marketUtility address and chainlink gas price aggregator address as arguments 13 | - Proposal to edit category `ResolveDispute` and set the action hash to `resolveDispute(uint256,uint256)` and contract code to `AM`, which enables execution of resolve dispute function in new contract 14 | - Initialise the AllMarkets contract ans start initial markets =>`AllMarkets.addInitialMarketTypesAndStart()`, pass MarketCreationRewards contract address, ETH identifier address(0xeee...eee), marketUtility address, date at which initial markets start, eth/usd chainlink aggregator address, btc/usd chainlink aggregator address as arguments. 15 | Edit categories 10, 15, 16, 17, 18, 25 and updated function hashes as per the new contract and set contract code to `AM` -------------------------------------------------------------------------------- /contracts/external/uniswap/oracleLibrary.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.5.0; 2 | 3 | import './solidity-interface.sol'; 4 | import './FixedPoint.sol'; 5 | 6 | // library with helper methods for oracles that are concerned with computing average prices 7 | library UniswapV2OracleLibrary { 8 | using FixedPoint for *; 9 | 10 | // helper function that returns the current block timestamp within the range of uint32, i.e. [0, 2**32 - 1] 11 | function currentBlockTimestamp() internal view returns (uint32) { 12 | return uint32(block.timestamp % 2 ** 32); 13 | } 14 | 15 | // produces the cumulative price using counterfactuals to save gas and avoid a call to sync. 16 | function currentCumulativePrices( 17 | address pair 18 | ) internal view returns (uint price0Cumulative, uint price1Cumulative, uint32 blockTimestamp) { 19 | blockTimestamp = currentBlockTimestamp(); 20 | price0Cumulative = IUniswapV2Pair(pair).price0CumulativeLast(); 21 | price1Cumulative = IUniswapV2Pair(pair).price1CumulativeLast(); 22 | 23 | // if time has elapsed since the last update on the pair, mock the accumulated price values 24 | (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast) = IUniswapV2Pair(pair).getReserves(); 25 | if (blockTimestampLast != blockTimestamp) { 26 | // subtraction overflow is desired 27 | uint32 timeElapsed = blockTimestamp - blockTimestampLast; 28 | // addition overflow is desired 29 | // counterfactual 30 | price0Cumulative += uint(FixedPoint.fraction(reserve1, reserve0)._x) * timeElapsed; 31 | // counterfactual 32 | price1Cumulative += uint(FixedPoint.fraction(reserve0, reserve1)._x) * timeElapsed; 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /test/utils/helper.js: -------------------------------------------------------------------------------- 1 | advanceTime = (time) => { 2 | return new Promise((resolve, reject) => { 3 | web3.currentProvider.send({ 4 | jsonrpc: '2.0', 5 | method: 'evm_increaseTime', 6 | params: [time], 7 | id: new Date().getTime() 8 | }, (err, result) => { 9 | if (err) { return reject(err) } 10 | return resolve(result) 11 | }) 12 | }) 13 | } 14 | advanceBlock = () => { 15 | return new Promise((resolve, reject) => { 16 | web3.currentProvider.send({ 17 | jsonrpc: '2.0', 18 | method: 'evm_mine', 19 | id: new Date().getTime() 20 | }, (err, result) => { 21 | if (err) { return reject(err) } 22 | const newBlockHash = web3.eth.getBlock('latest').hash 23 | return resolve(newBlockHash) 24 | }) 25 | }) 26 | } 27 | takeSnapshot = () => { 28 | return new Promise((resolve, reject) => { 29 | web3.currentProvider.send({ 30 | jsonrpc: '2.0', 31 | method: 'evm_snapshot', 32 | id: new Date().getTime() 33 | }, (err, snapshotId) => { 34 | if (err) { return reject(err) } 35 | return resolve(snapshotId) 36 | }) 37 | }) 38 | } 39 | revertToSnapShot = (id) => { 40 | return new Promise((resolve, reject) => { 41 | web3.currentProvider.send({ 42 | jsonrpc: '2.0', 43 | method: 'evm_revert', 44 | params: [id], 45 | id: new Date().getTime() 46 | }, (err, result) => { 47 | if (err) { return reject(err) } 48 | return resolve(result) 49 | }) 50 | }) 51 | } 52 | advanceTimeAndBlock = async (time) => { 53 | await advanceTime(time) 54 | await advanceBlock() 55 | return Promise.resolve(web3.eth.getBlock('latest')) 56 | } 57 | module.exports = { 58 | advanceTime, 59 | advanceBlock, 60 | advanceTimeAndBlock, 61 | takeSnapshot, 62 | revertToSnapShot 63 | } -------------------------------------------------------------------------------- /contracts/external/govblocks-protocol/Governed.sol: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2017 GovBlocks.io 2 | This program is free software: you can redistribute it and/or modify 3 | it under the terms of the GNU General Public License as published by 4 | the Free Software Foundation, either version 3 of the License, or 5 | (at your option) any later version. 6 | This program is distributed in the hope that it will be useful, 7 | but WITHOUT ANY WARRANTY; without even the implied warranty of 8 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 9 | GNU General Public License for more details. 10 | You should have received a copy of the GNU General Public License 11 | along with this program. If not, see http://www.gnu.org/licenses/ */ 12 | 13 | pragma solidity 0.5.7; 14 | 15 | 16 | contract IMaster { 17 | mapping(address => bool) public whitelistedSponsor; 18 | function dAppToken() public view returns(address); 19 | function isInternal(address _address) public view returns(bool); 20 | function getLatestAddress(bytes2 _module) public view returns(address); 21 | function isAuthorizedToGovern(address _toCheck) public view returns(bool); 22 | } 23 | 24 | 25 | contract Governed { 26 | 27 | address public masterAddress; // Name of the dApp, needs to be set by contracts inheriting this contract 28 | 29 | /// @dev modifier that allows only the authorized addresses to execute the function 30 | modifier onlyAuthorizedToGovern() { 31 | IMaster ms = IMaster(masterAddress); 32 | require(ms.getLatestAddress("GV") == msg.sender, "Not authorized"); 33 | _; 34 | } 35 | 36 | /// @dev checks if an address is authorized to govern 37 | function isAuthorizedToGovern(address _toCheck) public view returns(bool) { 38 | IMaster ms = IMaster(masterAddress); 39 | return (ms.getLatestAddress("GV") == _toCheck); 40 | } 41 | 42 | } -------------------------------------------------------------------------------- /test/utils/increaseTime.js: -------------------------------------------------------------------------------- 1 | const { latestTime } = require('./latestTime'); 2 | 3 | // Increases ganache time by the passed duration in seconds 4 | function increaseTime(duration) { 5 | const id = Date.now(); 6 | 7 | return new Promise((resolve, reject) => { 8 | web3.currentProvider.send( 9 | { 10 | jsonrpc: '2.0', 11 | method: 'evm_increaseTime', 12 | params: [duration], 13 | id: id 14 | }, 15 | err1 => { 16 | if (err1) return reject(err1); 17 | 18 | web3.currentProvider.send( 19 | { 20 | jsonrpc: '2.0', 21 | method: 'evm_mine', 22 | id: id + 1 23 | }, 24 | (err2, res) => { 25 | return err2 ? reject(err2) : resolve(res); 26 | } 27 | ); 28 | } 29 | ); 30 | }); 31 | } 32 | 33 | /** 34 | * Beware that due to the need of calling two separate ganache methods and rpc calls overhead 35 | * it's hard to increase time precisely to a target point so design your test to tolerate 36 | * small fluctuations from time to time. 37 | * 38 | * @param target time in seconds 39 | */ 40 | async function increaseTimeTo(target) { 41 | const now = await latestTime(); 42 | 43 | if (target < now) 44 | throw Error( 45 | `Cannot increase current time(${now}) to a moment in the past(${target})` 46 | ); 47 | const diff = target - now; 48 | return increaseTime(diff); 49 | } 50 | 51 | const duration = { 52 | seconds: function(val) { 53 | return val; 54 | }, 55 | minutes: function(val) { 56 | return val * this.seconds(60); 57 | }, 58 | hours: function(val) { 59 | return val * this.minutes(60); 60 | }, 61 | days: function(val) { 62 | return val * this.hours(24); 63 | }, 64 | weeks: function(val) { 65 | return val * this.days(7); 66 | }, 67 | years: function(val) { 68 | return val * this.days(365); 69 | } 70 | }; 71 | 72 | module.exports = { 73 | increaseTime, 74 | increaseTimeTo, 75 | duration 76 | }; 77 | -------------------------------------------------------------------------------- /contracts/external/proxy/UpgradeabilityProxy.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.5.7; 2 | 3 | import "./Proxy.sol"; 4 | 5 | 6 | /** 7 | * @title UpgradeabilityProxy 8 | * @dev This contract represents a proxy where the implementation address to which it will delegate can be upgraded 9 | */ 10 | contract UpgradeabilityProxy is Proxy { 11 | /** 12 | * @dev This event will be emitted every time the implementation gets upgraded 13 | * @param implementation representing the address of the upgraded implementation 14 | */ 15 | event Upgraded(address indexed implementation); 16 | 17 | // Storage position of the address of the current implementation 18 | bytes32 private constant IMPLEMENTATION_POSITION = keccak256("org.govblocks.proxy.implementation"); 19 | 20 | /** 21 | * @dev Constructor function 22 | */ 23 | constructor() public {} 24 | 25 | /** 26 | * @dev Tells the address of the current implementation 27 | * @return address of the current implementation 28 | */ 29 | function implementation() public view returns (address impl) { 30 | bytes32 position = IMPLEMENTATION_POSITION; 31 | assembly { 32 | impl := sload(position) 33 | } 34 | } 35 | 36 | /** 37 | * @dev Sets the address of the current implementation 38 | * @param _newImplementation address representing the new implementation to be set 39 | */ 40 | function _setImplementation(address _newImplementation) internal { 41 | bytes32 position = IMPLEMENTATION_POSITION; 42 | assembly { 43 | sstore(position, _newImplementation) 44 | } 45 | } 46 | 47 | /** 48 | * @dev Upgrades the implementation address 49 | * @param _newImplementation representing the address of the new implementation to be set 50 | */ 51 | function _upgradeTo(address _newImplementation) internal { 52 | address currentImplementation = implementation(); 53 | require(currentImplementation != _newImplementation); 54 | _setImplementation(_newImplementation); 55 | emit Upgraded(_newImplementation); 56 | } 57 | } -------------------------------------------------------------------------------- /contracts/mock/MockChainLinkAggregator.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.5.7; 2 | 3 | import "../interfaces/IChainLinkOracle.sol"; 4 | contract MockChainLinkAggregator is IChainLinkOracle{ 5 | 6 | int256 latestAns = 934999802346; 7 | uint256 updatedAt = now; 8 | 9 | struct RoundData { 10 | uint80 roundId; 11 | int256 answer; 12 | uint256 startedAt; 13 | uint256 updatedAt; 14 | uint80 answeredInRound; 15 | } 16 | 17 | mapping(uint80 => RoundData) public roundData; 18 | uint80 public currentRound; 19 | 20 | constructor() public { 21 | currentRound = 0; 22 | roundData[0] = RoundData(uint80(0),latestAns, updatedAt, updatedAt, uint80(0)); 23 | } 24 | 25 | function decimals() external view returns (uint8) { 26 | return uint8(8); 27 | } 28 | /** 29 | * @dev Gets the latest answer of chainLink oracle. 30 | * @return int256 representing the latest answer of chainLink oracle. 31 | */ 32 | function latestAnswer() external view returns (int256) 33 | { 34 | return roundData[currentRound].answer; 35 | 36 | } 37 | 38 | /** 39 | * @dev Set the latest answer of chainLink oracle. 40 | * @param _latestAnswer The latest anser of chainLink oracle. 41 | */ 42 | function setLatestAnswer(int256 _latestAnswer) public 43 | { 44 | currentRound = currentRound + uint80(1); 45 | roundData[currentRound] = RoundData(currentRound,_latestAnswer, now, now, currentRound); 46 | } 47 | 48 | function getRoundData(uint80 _roundId) 49 | external 50 | view 51 | returns ( 52 | uint80 roundId, 53 | int256 answer, 54 | uint256 startedAt, 55 | uint256 updatedAt, 56 | uint80 answeredInRound 57 | ) { 58 | return (roundData[_roundId].roundId, roundData[_roundId].answer, roundData[_roundId].startedAt, 59 | roundData[_roundId].updatedAt,roundData[_roundId].answeredInRound); 60 | } 61 | 62 | function latestRoundData() 63 | external 64 | view 65 | returns ( 66 | uint80 roundId, 67 | int256 answer, 68 | uint256 startedAt, 69 | uint256 updatedAt, 70 | uint80 answeredInRound 71 | ) { 72 | return (roundData[currentRound].roundId, roundData[currentRound].answer, roundData[currentRound].startedAt, 73 | roundData[currentRound].updatedAt,roundData[currentRound].answeredInRound); 74 | } 75 | 76 | } -------------------------------------------------------------------------------- /contracts/mock/MockChainLinkGasPriceAgg.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.5.7; 2 | 3 | import "../interfaces/IChainLinkOracle.sol"; 4 | contract MockChainLinkGasPriceAgg is IChainLinkOracle{ 5 | 6 | int256 latestAns = 45000000000; 7 | uint256 updatedAt = now; 8 | 9 | struct RoundData { 10 | uint80 roundId; 11 | int256 answer; 12 | uint256 startedAt; 13 | uint256 updatedAt; 14 | uint80 answeredInRound; 15 | } 16 | 17 | mapping(uint80 => RoundData) public roundData; 18 | uint80 public currentRound; 19 | 20 | constructor() public { 21 | currentRound = 0; 22 | roundData[0] = RoundData(uint80(0),latestAns, updatedAt, updatedAt, uint80(0)); 23 | } 24 | 25 | function decimals() external view returns (uint8) { 26 | return uint8(8); 27 | } 28 | /** 29 | * @dev Gets the latest answer of chainLink oracle. 30 | * @return int256 representing the latest answer of chainLink oracle. 31 | */ 32 | function latestAnswer() external view returns (int256) 33 | { 34 | return roundData[currentRound].answer; 35 | 36 | } 37 | 38 | /** 39 | * @dev Set the latest answer of chainLink oracle. 40 | * @param _latestAnswer The latest anser of chainLink oracle. 41 | */ 42 | function setLatestAnswer(int256 _latestAnswer) public 43 | { 44 | currentRound = currentRound + uint80(1); 45 | roundData[currentRound] = RoundData(currentRound,_latestAnswer, now, now, currentRound); 46 | } 47 | 48 | function getRoundData(uint80 _roundId) 49 | external 50 | view 51 | returns ( 52 | uint80 roundId, 53 | int256 answer, 54 | uint256 startedAt, 55 | uint256 updatedAt, 56 | uint80 answeredInRound 57 | ) { 58 | return (roundData[_roundId].roundId, roundData[_roundId].answer, roundData[_roundId].startedAt, 59 | roundData[_roundId].updatedAt,roundData[_roundId].answeredInRound); 60 | } 61 | 62 | function latestRoundData() 63 | external 64 | view 65 | returns ( 66 | uint80 roundId, 67 | int256 answer, 68 | uint256 startedAt, 69 | uint256 updatedAt, 70 | uint80 answeredInRound 71 | ) { 72 | return (roundData[currentRound].roundId, roundData[currentRound].answer, roundData[currentRound].startedAt, 73 | roundData[currentRound].updatedAt,roundData[currentRound].answeredInRound); 74 | } 75 | 76 | } -------------------------------------------------------------------------------- /MajorFunctions.md: -------------------------------------------------------------------------------- 1 | ### Major Functions in PLOTX Platform 2 |
Smart contracts for PlotX - Curated prediction markets for crypto traders . https://plotx.io/.
7 | 8 | 9 | ## Getting Started 10 | 11 | These instructions will get you a copy of the project up and running on your local machine for development and testing purposes. 12 | 13 | 14 | ### Requirements 15 | ``` 16 | Node >= 10.x 17 | ``` 18 | 19 | 20 | ### Installing 21 | Firstly, you need to clone this repo. You can do so by downloading the repo as a zip and unpacking or using the following git command 22 | 23 | ``` 24 | git clone https://github.com/plotx/smart-contracts.git 25 | ``` 26 | 27 | Now, It's time to install the dependencies. Enter the smart-contracts directory and use 28 | 29 | ``` 30 | npm install 31 | ``` 32 | If you want, you can run the test cases using 33 | ``` 34 | npm run test 35 | ``` 36 | And run generate the coverage report using 37 | ``` 38 | npm run coverage 39 | ``` 40 | 41 | ### Contract Addresses - Mainnet 42 | - PLOT Token: 0x72F020f8f3E8fd9382705723Cd26380f8D0c66Bb 43 | - Master: 0x03c41c5Aff6D541EF7D4c51c8B2E32a5d4427275 44 | - MarketRegistry: 0xE210330d6768030e816d223836335079C7A0c851 45 | - AllMarkets: 0xb9448E3a0d95cFF578F9508084A0ed92D724c29A 46 | - MarketCreationRewards: 0x22376814188De44e8B6f482daa98B050ac190B46 47 | - MarketUtility: 0x2330058D49fA61D5C5405fA8B17fcD823c59F7Bb 48 | - Governance: 0x16763F192d529B420F33B699dC72F39f16620717 49 | - ProposalCategory: 0x2D90743ef134b35cE415855F1c38ca47d65b314C 50 | - MemberRoles: 0xda06bcd22a68Fa40B63867277aA0eB34702fd80D 51 | - TokenController: 0x12d7053Efc680Ba6671F8Cb96d1421D906ce3dE2 52 | - bPLOT Token: 0x82cB6Cd09Bf80fB4014935871fF553b027255D36 53 | - Vesting: 0x5172C83B5316b86861802d29746d8435f4cB67e6 54 | 55 | Market Implementation Addresses 56 | - ETH/USD: 0x25cf9d73b711bff4d3445a0f7f2e63ade5133e67 57 | - BTC/USD: 0x5d24cf40ead0601893c212ff3af4895dc42a760b 58 | 59 | ### Contract Addresses - Kovan 60 | - PLOT Token: 0x1616111F8914F377c22DC576ca6BaB947597022F 61 | - Master: 0x6bd86cf45fff86300910599107e24dd5db9e1f51 62 | - MarketRegistry: 0x9f94a65878ea576AbeEA36857587110bcF1BBca5 63 | - MarketUtility: 0x388716cC71CcFCCe98BAF48E61e6D1F8D259eccC 64 | - Governance: 0xab4C2C278862931f2929E434464CFc3dC340C6D4 65 | - ProposalCategory: 0xEAf8e09C80609af4b29946D62F46C26888541332 66 | - MemberRoles: 0x6C31400177CD31d48f7bf47Cc333ba0651b17d11 67 | - TokenController: 0xb27E5Fa57B37be78ddE637F705Bd8bd440ed19af 68 | - bPLOT Token: 0xc84244c52Ff9F1f103F624388DcCc36801062b7a 69 | - Vesting: 0xdd8cc36531cad81b08704e35cb22cb8f525f4159 70 | 71 | Market Implementation Addresses 72 | - ETH/USD: 0x8f2d95c4c35d5cf6db1a794ff6a3d97178175b9d 73 | - BTC/USD: 0x7930515cd9dfd91fb65bfe60b0a64e06576c4b19 74 | 75 | -------------------------------------------------------------------------------- /contracts/mock/TokenMock.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.5.7; 2 | 3 | import "../external/openzeppelin-solidity/token/ERC20/ERC20.sol"; 4 | 5 | 6 | contract TokenMock is ERC20 { 7 | 8 | string public name; 9 | string public symbol; 10 | uint8 public decimals = 18; 11 | 12 | constructor(string memory tokenName, string memory tokenSymbol) public { 13 | name = tokenName; 14 | symbol = tokenSymbol; 15 | } 16 | 17 | function mint(uint256 amount) public returns (uint256) { 18 | _mint(msg.sender, amount); 19 | return 0; 20 | } 21 | 22 | /** 23 | * @dev burns an amount of the tokens of the message sender 24 | * account. 25 | * @param amount The amount that will be burnt. 26 | */ 27 | function burn(uint256 amount) public returns (bool) { 28 | _burn(msg.sender, amount); 29 | return true; 30 | } 31 | 32 | /** 33 | * @dev Burns a specific amount of tokens from the target address and decrements allowance 34 | * @param from address The address which you want to send tokens from 35 | * @param value uint256 The amount of token to be burned 36 | */ 37 | function burnFrom(address from, uint256 value) public returns (bool) { 38 | _burnFrom(from, value); 39 | return true; 40 | } 41 | 42 | /** 43 | * @dev Transfer token for a specified address 44 | * @param to The address to transfer to. 45 | * @param value The amount to be transferred. 46 | */ 47 | function transfer(address to, uint256 value) public returns (bool) { 48 | 49 | require(value <= _balances[msg.sender]); 50 | _transfer(msg.sender, to, value); 51 | return true; 52 | } 53 | 54 | /** 55 | * @dev Transfer tokens from one address to another 56 | * @param from address The address which you want to send tokens from 57 | * @param to address The address which you want to transfer to 58 | * @param value uint256 the amount of tokens to be transferred 59 | */ 60 | function transferFrom( 61 | address from, 62 | address to, 63 | uint256 value 64 | ) 65 | public 66 | returns (bool) 67 | { 68 | _transferFrom(from, to, value); 69 | return true; 70 | } 71 | 72 | /** 73 | * @dev Gets the balance of the specified address. 74 | * @param owner The address to query the balance of. 75 | * @return An uint256 representing the amount owned by the passed address. 76 | */ 77 | function balanceOf(address owner) public view returns (uint256) { 78 | return _balances[owner]; 79 | } 80 | 81 | /** 82 | * @dev function that mints an amount of the token and assigns it to 83 | * an account. 84 | * @param account The account that will receive the created tokens. 85 | * @param amount The amount that will be created. 86 | */ 87 | function mint(address account, uint256 amount) public returns(bool) { 88 | _mint(account, amount); 89 | return true; 90 | } 91 | 92 | } 93 | -------------------------------------------------------------------------------- /contracts/MarketUtilityV2.sol: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2020 PlotX.io 2 | 3 | This program is free software: you can redistribute it and/or modify 4 | it under the terms of the GNU General Public License as published by 5 | the Free Software Foundation, either version 3 of the License, or 6 | (at your option) any later version. 7 | 8 | This program is distributed in the hope that it will be useful, 9 | but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | GNU General Public License for more details. 12 | 13 | You should have received a copy of the GNU General Public License 14 | along with this program. If not, see http://www.gnu.org/licenses/ */ 15 | 16 | pragma solidity 0.5.7; 17 | 18 | import "./MarketUtility.sol"; 19 | 20 | contract MarketUtilityV2 is MarketUtility { 21 | 22 | using SafeMath64 for uint64; 23 | 24 | function setAuthorizedAddress(address _allMarketsContract) external { 25 | require(msg.sender == initiater); 26 | authorizedAddress = _allMarketsContract; 27 | } 28 | 29 | function calculateOptionRange(uint _optionRangePerc, uint64 _decimals, uint8 _roundOfToNearest, address _marketFeed) external view returns(uint64 _minValue, uint64 _maxValue) { 30 | uint currentPrice = getAssetPriceUSD(_marketFeed); 31 | uint optionRangePerc = currentPrice.mul(_optionRangePerc.div(2)).div(10000); 32 | _minValue = uint64((ceil(currentPrice.sub(optionRangePerc).div(_roundOfToNearest), 10**_decimals)).mul(_roundOfToNearest)); 33 | _maxValue = uint64((ceil(currentPrice.add(optionRangePerc).div(_roundOfToNearest), 10**_decimals)).mul(_roundOfToNearest)); 34 | } 35 | 36 | function calculatePredictionPoints(address _user, bool multiplierApplied, uint _predictionStake, address _asset, uint64 totalPredictionPoints, uint64 predictionPointsOnOption) external view returns(uint64 predictionPoints, bool isMultiplierApplied) { 37 | uint _stakeValue = getAssetValueETH(_asset, _predictionStake.mul(1e10)); 38 | if(_stakeValue < minPredictionAmount || _stakeValue > maxPredictionAmount) { 39 | return (0, isMultiplierApplied); 40 | } 41 | uint64 _optionPrice = getOptionPrice(totalPredictionPoints, predictionPointsOnOption); 42 | predictionPoints = uint64(_stakeValue.div(1e10)).div(_optionPrice); 43 | if(!multiplierApplied) { 44 | uint256 _predictionPoints; 45 | (_predictionPoints, isMultiplierApplied) = checkMultiplier(_asset, _user, _predictionStake.mul(1e10), predictionPoints, _stakeValue); 46 | predictionPoints = uint64(_predictionPoints); 47 | } 48 | } 49 | 50 | function getOptionPrice(uint64 totalPredictionPoints, uint64 predictionPointsOnOption) public view returns(uint64 _optionPrice) { 51 | if(totalPredictionPoints > 0) { 52 | _optionPrice = (predictionPointsOnOption.mul(100)).div(totalPredictionPoints) + 100; 53 | } else { 54 | _optionPrice = 100; 55 | } 56 | } 57 | 58 | function ceil(uint256 a, uint256 m) internal pure returns (uint256) { 59 | return ((a + m - 1) / m) * m; 60 | } 61 | 62 | } -------------------------------------------------------------------------------- /contracts/external/openzeppelin-solidity/token/ERC20/IERC20.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.0; 2 | 3 | /** 4 | * @dev Interface of the ERC20 standard as defined in the EIP. Does not include 5 | * the optional functions; to access them see `ERC20Detailed`. 6 | */ 7 | interface IERC20 { 8 | /** 9 | * @dev Returns the amount of tokens in existence. 10 | */ 11 | function totalSupply() external view returns (uint256); 12 | 13 | /** 14 | * @dev Returns the amount of tokens owned by `account`. 15 | */ 16 | function balanceOf(address account) external view returns (uint256); 17 | 18 | /** 19 | * @dev Moves `amount` tokens from the caller's account to `recipient`. 20 | * 21 | * Returns a boolean value indicating whether the operation succeeded. 22 | * 23 | * Emits a `Transfer` event. 24 | */ 25 | function transfer(address recipient, uint256 amount) external returns (bool); 26 | 27 | /** 28 | * @dev Mints `amount` tokens to address `account`. 29 | * 30 | * Returns a boolean value indicating whether the operation succeeded. 31 | * 32 | * Emits a `Transfer` event. 33 | */ 34 | function mint(address account, uint256 amount) external returns (bool); 35 | /** 36 | * @dev Returns the remaining number of tokens that `spender` will be 37 | * allowed to spend on behalf of `owner` through `transferFrom`. This is 38 | * zero by default. 39 | * 40 | * This value changes when `approve` or `transferFrom` are called. 41 | */ 42 | function allowance(address owner, address spender) external view returns (uint256); 43 | 44 | /** 45 | * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. 46 | * 47 | * Returns a boolean value indicating whether the operation succeeded. 48 | * 49 | * > Beware that changing an allowance with this method brings the risk 50 | * that someone may use both the old and the new allowance by unfortunate 51 | * transaction ordering. One possible solution to mitigate this race 52 | * condition is to first reduce the spender's allowance to 0 and set the 53 | * desired value afterwards: 54 | * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 55 | * 56 | * Emits an `Approval` event. 57 | */ 58 | function approve(address spender, uint256 amount) external returns (bool); 59 | 60 | /** 61 | * @dev Moves `amount` tokens from `sender` to `recipient` using the 62 | * allowance mechanism. `amount` is then deducted from the caller's 63 | * allowance. 64 | * 65 | * Returns a boolean value indicating whether the operation succeeded. 66 | * 67 | * Emits a `Transfer` event. 68 | */ 69 | function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); 70 | 71 | /** 72 | * @dev Emitted when `value` tokens are moved from one account (`from`) to 73 | * another (`to`). 74 | * 75 | * Note that `value` may be zero. 76 | */ 77 | event Transfer(address indexed from, address indexed to, uint256 value); 78 | 79 | /** 80 | * @dev Emitted when the allowance of a `spender` for an `owner` is set by 81 | * a call to `approve`. `value` is the new allowance. 82 | */ 83 | event Approval(address indexed owner, address indexed spender, uint256 value); 84 | } 85 | -------------------------------------------------------------------------------- /contracts/interfaces/IMarketRegistry.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.5.7; 2 | 3 | contract IMarketRegistry { 4 | 5 | enum MarketType { 6 | HourlyMarket, 7 | DailyMarket, 8 | WeeklyMarket 9 | } 10 | address public owner; 11 | address public tokenController; 12 | address public marketUtility; 13 | bool public marketCreationPaused; 14 | 15 | mapping(address => bool) public isMarket; 16 | function() external payable{} 17 | 18 | function marketDisputeStatus(address _marketAddress) public view returns(uint _status); 19 | 20 | function burnDisputedProposalTokens(uint _proposaId) external; 21 | 22 | function isWhitelistedSponsor(address _address) public view returns(bool); 23 | 24 | function transferAssets(address _asset, address _to, uint _amount) external; 25 | 26 | /** 27 | * @dev Initialize the PlotX. 28 | * @param _marketConfig The address of market config. 29 | * @param _plotToken The address of PLOT token. 30 | */ 31 | function initiate(address _defaultAddress, address _marketConfig, address _plotToken, address payable[] memory _configParams) public; 32 | 33 | /** 34 | * @dev Create proposal if user wants to raise the dispute. 35 | * @param proposalTitle The title of proposal created by user. 36 | * @param description The description of dispute. 37 | * @param solutionHash The ipfs solution hash. 38 | * @param actionHash The action hash for solution. 39 | * @param stakeForDispute The token staked to raise the diospute. 40 | * @param user The address who raises the dispute. 41 | */ 42 | function createGovernanceProposal(string memory proposalTitle, string memory description, string memory solutionHash, bytes memory actionHash, uint256 stakeForDispute, address user, uint256 ethSentToPool, uint256 tokenSentToPool, uint256 proposedValue) public { 43 | } 44 | 45 | /** 46 | * @dev Emits the PlacePrediction event and sets user data. 47 | * @param _user The address who placed prediction. 48 | * @param _value The amount of ether user staked. 49 | * @param _predictionPoints The positions user will get. 50 | * @param _predictionAsset The prediction assets user will get. 51 | * @param _prediction The option range on which user placed prediction. 52 | * @param _leverage The leverage selected by user at the time of place prediction. 53 | */ 54 | function setUserGlobalPredictionData(address _user,uint _value, uint _predictionPoints, address _predictionAsset, uint _prediction,uint _leverage) public{ 55 | } 56 | 57 | /** 58 | * @dev Emits the claimed event. 59 | * @param _user The address who claim their reward. 60 | * @param _reward The reward which is claimed by user. 61 | * @param incentives The incentives of user. 62 | * @param incentiveToken The incentive tokens of user. 63 | */ 64 | function callClaimedEvent(address _user , uint[] memory _reward, address[] memory predictionAssets, uint incentives, address incentiveToken) public { 65 | } 66 | 67 | /** 68 | * @dev Emits the MarketResult event. 69 | * @param _totalReward The amount of reward to be distribute. 70 | * @param _winningOption The winning option of the market. 71 | * @param _closeValue The closing value of the market currency. 72 | */ 73 | function callMarketResultEvent(uint[] memory _totalReward, uint _winningOption, uint _closeValue, uint roundId) public { 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /contracts/mock/DummyTokenMock.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.5.7; 2 | 3 | import "../external/openzeppelin-solidity/token/ERC20/ERC20.sol"; 4 | 5 | // To branch coverage of token transer 6 | contract DummyTokenMock is ERC20 { 7 | 8 | string public name; 9 | string public symbol; 10 | uint8 public decimals = 18; 11 | 12 | mapping(address=>bool) _dummyBit; 13 | 14 | bool public retBit; 15 | 16 | constructor(string memory tokenName, string memory tokenSymbol) public { 17 | name = tokenName; 18 | symbol = tokenSymbol; 19 | } 20 | 21 | function mint(uint256 amount) public returns (uint256) { 22 | _mint(msg.sender, amount); 23 | return 0; 24 | } 25 | 26 | function setRetBit(bool _a) public { 27 | retBit = _a; 28 | } 29 | 30 | /** 31 | * @dev burns an amount of the tokens of the message sender 32 | * account. 33 | * @param amount The amount that will be burnt. 34 | */ 35 | function burn(uint256 amount) public returns (bool) { 36 | _burn(msg.sender, amount); 37 | return true; 38 | } 39 | 40 | /** 41 | * @dev Burns a specific amount of tokens from the target address and decrements allowance 42 | * @param from address The address which you want to send tokens from 43 | * @param value uint256 The amount of token to be burned 44 | */ 45 | function burnFrom(address from, uint256 value) public returns (bool) { 46 | _burnFrom(from, value); 47 | return true; 48 | } 49 | 50 | /** 51 | * @dev Transfer token for a specified address 52 | * @param to The address to transfer to. 53 | * @param value The amount to be transferred. 54 | */ 55 | function transfer(address to, uint256 value) public returns (bool) { 56 | 57 | // _transfer(msg.sender, to, value); 58 | return retBit; 59 | } 60 | 61 | /** 62 | * @dev Transfer tokens from one address to another 63 | * @param from address The address which you want to send tokens from 64 | * @param to address The address which you want to transfer to 65 | * @param value uint256 the amount of tokens to be transferred 66 | */ 67 | function transferFrom( 68 | address from, 69 | address to, 70 | uint256 value 71 | ) 72 | public 73 | returns (bool) 74 | { 75 | // _transferFrom(from, to, value); 76 | return retBit; 77 | } 78 | 79 | /** 80 | * @dev Gets the balance of the specified address. 81 | * @param owner The address to query the balance of. 82 | * @return An uint256 representing the amount owned by the passed address. 83 | */ 84 | function balanceOf(address owner) public view returns (uint256) { 85 | return _balances[owner]; 86 | } 87 | 88 | /** 89 | * @dev function that mints an amount of the token and assigns it to 90 | * an account. 91 | * @param account The account that will receive the created tokens. 92 | * @param amount The amount that will be created. 93 | */ 94 | function mint(address account, uint256 amount) public returns(bool) { 95 | _mint(account, amount); 96 | return true; 97 | } 98 | 99 | function isLockedForGV(address _of) public view returns(bool) { 100 | return _dummyBit[_of]; 101 | } 102 | 103 | function setDummyBit(address _of, bool _val) public { 104 | _dummyBit[_of] = _val; 105 | } 106 | 107 | } 108 | -------------------------------------------------------------------------------- /contracts/external/govblocks-protocol/interfaces/IMemberRoles.sol: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2017 GovBlocks.io 2 | This program is free software: you can redistribute it and/or modify 3 | it under the terms of the GNU General Public License as published by 4 | the Free Software Foundation, either version 3 of the License, or 5 | (at your option) any later version. 6 | This program is distributed in the hope that it will be useful, 7 | but WITHOUT ANY WARRANTY; without even the implied warranty of 8 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 9 | GNU General Public License for more details. 10 | You should have received a copy of the GNU General Public License 11 | along with this program. If not, see http://www.gnu.org/licenses/ */ 12 | 13 | pragma solidity 0.5.7; 14 | 15 | 16 | contract IMemberRoles { 17 | 18 | event MemberRole(uint256 indexed roleId, bytes32 roleName, string roleDescription); 19 | 20 | enum Role {UnAssigned, AdvisoryBoard, TokenHolder, DisputeResolution} 21 | 22 | function setInititorAddress(address _initiator) external; 23 | 24 | /// @dev Adds new member role 25 | /// @param _roleName New role name 26 | /// @param _roleDescription New description hash 27 | /// @param _authorized Authorized member against every role id 28 | function addRole(bytes32 _roleName, string memory _roleDescription, address _authorized) public; 29 | 30 | /// @dev Assign or Delete a member from specific role. 31 | /// @param _memberAddress Address of Member 32 | /// @param _roleId RoleId to update 33 | /// @param _active active is set to be True if we want to assign this role to member, False otherwise! 34 | function updateRole(address _memberAddress, uint _roleId, bool _active) public; 35 | 36 | /// @dev Change Member Address who holds the authority to Add/Delete any member from specific role. 37 | /// @param _roleId roleId to update its Authorized Address 38 | /// @param _authorized New authorized address against role id 39 | function changeAuthorized(uint _roleId, address _authorized) public; 40 | 41 | /// @dev Return number of member roles 42 | function totalRoles() public view returns(uint256); 43 | 44 | /// @dev Gets the member addresses assigned by a specific role 45 | /// @param _memberRoleId Member role id 46 | /// @return roleId Role id 47 | /// @return allMemberAddress Member addresses of specified role id 48 | function members(uint _memberRoleId) public view returns(uint, address[] memory allMemberAddress); 49 | 50 | /// @dev Gets all members' length 51 | /// @param _memberRoleId Member role id 52 | /// @return memberRoleData[_memberRoleId].memberAddress.length Member length 53 | function numberOfMembers(uint _memberRoleId) public view returns(uint); 54 | 55 | /// @dev Return member address who holds the right to add/remove any member from specific role. 56 | function authorized(uint _memberRoleId) public view returns(address); 57 | 58 | /// @dev Get All role ids array that has been assigned to a member so far. 59 | function roles(address _memberAddress) public view returns(uint[] memory assignedRoles); 60 | 61 | /// @dev Returns true if the given role id is assigned to a member. 62 | /// @param _memberAddress Address of member 63 | /// @param _roleId Checks member's authenticity with the roleId. 64 | /// i.e. Returns true if this roleId is assigned to member 65 | function checkRole(address _memberAddress, uint _roleId) public view returns(bool); 66 | } -------------------------------------------------------------------------------- /contracts/interfaces/IMarket.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.5.7; 2 | 3 | contract IMarket { 4 | 5 | enum PredictionStatus { 6 | Live, 7 | InSettlement, 8 | Cooling, 9 | InDispute, 10 | Settled 11 | } 12 | 13 | struct MarketData { 14 | uint64 startTime; 15 | uint64 predictionTime; 16 | uint64 neutralMinValue; 17 | uint64 neutralMaxValue; 18 | } 19 | 20 | struct MarketSettleData { 21 | uint64 WinningOption; 22 | uint64 settleTime; 23 | } 24 | 25 | MarketSettleData public marketSettleData; 26 | 27 | MarketData public marketData; 28 | 29 | function WinningOption() public view returns(uint256); 30 | 31 | function marketCurrency() public view returns(bytes32); 32 | 33 | function getMarketFeedData() public view returns(uint8, bytes32, address); 34 | 35 | function settleMarket() external; 36 | 37 | function getTotalStakedValueInPLOT() external view returns(uint256); 38 | 39 | /** 40 | * @dev Initialize the market. 41 | * @param _startTime The time at which market will create. 42 | * @param _predictionTime The time duration of market. 43 | * @param _minValue The minimum value of middle option range. 44 | * @param _maxValue The maximum value of middle option range. 45 | */ 46 | function initiate(uint64 _startTime, uint64 _predictionTime, uint64 _minValue, uint64 _maxValue) public payable; 47 | 48 | /** 49 | * @dev Resolve the dispute if wrong value passed at the time of market result declaration. 50 | * @param accepted The flag defining that the dispute raised is accepted or not 51 | * @param finalResult The final correct value of market currency. 52 | */ 53 | function resolveDispute(bool accepted, uint256 finalResult) external payable; 54 | 55 | /** 56 | * @dev Gets the market data. 57 | * @return _marketCurrency bytes32 representing the currency or stock name of the market. 58 | * @return minvalue uint[] memory representing the minimum range of all the options of the market. 59 | * @return maxvalue uint[] memory representing the maximum range of all the options of the market. 60 | * @return _optionPrice uint[] memory representing the option price of each option ranges of the market. 61 | * @return _ethStaked uint[] memory representing the ether staked on each option ranges of the market. 62 | * @return _plotStaked uint[] memory representing the plot staked on each option ranges of the market. 63 | * @return _predictionType uint representing the type of market. 64 | * @return _expireTime uint representing the expire time of the market. 65 | * @return _predictionStatus uint representing the status of the market. 66 | */ 67 | function getData() external view 68 | returns ( 69 | bytes32 _marketCurrency,uint[] memory minvalue,uint[] memory maxvalue, 70 | uint[] memory _optionPrice, uint[] memory _ethStaked, uint[] memory _plotStaked,uint _predictionType, 71 | uint _expireTime, uint _predictionStatus 72 | ); 73 | 74 | // /** 75 | // * @dev Gets the pending return. 76 | // * @param _user The address to specify the return of. 77 | // * @return uint representing the pending return amount. 78 | // */ 79 | // function getPendingReturn(address _user) external view returns(uint[] memory returnAmount, address[] memory _predictionAssets, uint[] memory incentive, address[] memory _incentiveTokens); 80 | 81 | /** 82 | * @dev Claim the return amount of the specified address. 83 | * @param _user The address to query the claim return amount of. 84 | * @return Flag, if 0:cannot claim, 1: Already Claimed, 2: Claimed 85 | */ 86 | function claimReturn(address payable _user) public returns(uint256); 87 | 88 | } -------------------------------------------------------------------------------- /contracts/interfaces/IMarketUtility.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.5.7; 2 | contract IMarketUtility { 3 | 4 | function initialize(address payable[] calldata _addressParams, address _initiater) external; 5 | 6 | /** 7 | * @dev to Set authorized address to update parameters 8 | */ 9 | function setAuthorizedAddres() public; 10 | 11 | /** 12 | * @dev to update uint parameters in Market Config 13 | */ 14 | function updateUintParameters(bytes8 code, uint256 value) external; 15 | 16 | /** 17 | * @dev to Update address parameters in Market Config 18 | */ 19 | function updateAddressParameters(bytes8 code, address payable value) external; 20 | 21 | /** 22 | * @dev Get Parameters required to initiate market 23 | * @return Addresses of tokens to be distributed as incentives 24 | * @return Cool down time for market 25 | * @return Rate 26 | * @return Commission percent for predictions with ETH 27 | * @return Commission percent for predictions with PLOT 28 | **/ 29 | function getMarketInitialParams() public view returns(address[] memory, uint , uint, uint, uint); 30 | 31 | function getAssetPriceUSD(address _currencyAddress) external view returns(uint latestAnswer); 32 | 33 | function getAssetValueETH(address _currencyAddress, uint256 _amount) 34 | public 35 | view 36 | returns (uint256 tokenEthValue); 37 | 38 | function checkMultiplier(address _asset, address _user, uint _predictionStake, uint predictionPoints, uint _stakeValue) public view returns(uint, bool); 39 | 40 | function calculatePredictionPoints(address _user, bool multiplierApplied, uint _predictionStake, address _asset, uint64 totalPredictionPoints, uint64 predictionPointsOnOption) external view returns(uint64 predictionPoints, bool isMultiplierApplied); 41 | 42 | function calculateOptionRange(uint _optionRangePerc, uint64 _decimals, uint8 _roundOfToNearest, address _marketFeed) external view returns(uint64 _minValue, uint64 _maxValue); 43 | 44 | function getOptionPrice(uint64 totalPredictionPoints, uint64 predictionPointsOnOption) public view returns(uint64 _optionPrice); 45 | 46 | function getPriceFeedDecimals(address _priceFeed) public view returns(uint8); 47 | 48 | function getValueAndMultiplierParameters(address _asset, uint256 _amount) 49 | public 50 | view 51 | returns (uint256, uint256); 52 | 53 | function update() external; 54 | 55 | function calculatePredictionValue(uint[] memory params, address asset, address user, address marketFeedAddress, bool _checkMultiplier) public view returns(uint _predictionValue, bool _multiplierApplied); 56 | 57 | /** 58 | * @dev Get basic market details 59 | * @return Minimum amount required to predict in market 60 | * @return Percentage of users leveraged amount to deduct when placed in wrong prediction 61 | * @return Decimal points for prediction positions 62 | **/ 63 | function getBasicMarketDetails() 64 | public 65 | view 66 | returns ( 67 | uint256, 68 | uint256, 69 | uint256, 70 | uint256 71 | ); 72 | 73 | function getDisputeResolutionParams() public view returns (uint256); 74 | function calculateOptionPrice(uint[] memory params, address marketFeedAddress) public view returns(uint _optionPrice); 75 | 76 | /** 77 | * @dev Get price of provided feed address 78 | * @param _currencyFeedAddress Feed Address of currency on which market options are based on 79 | * @return Current price of the market currency 80 | **/ 81 | function getSettlemetPrice( 82 | address _currencyFeedAddress, 83 | uint256 _settleTime 84 | ) public view returns (uint256 latestAnswer, uint256 roundId); 85 | } 86 | -------------------------------------------------------------------------------- /contracts/Airdrop.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.5.7; 2 | 3 | import "./PlotXToken.sol"; 4 | import "./external/openzeppelin-solidity/math/SafeMath.sol"; 5 | import "./external/openzeppelin-solidity/token/ERC20/ERC20.sol"; 6 | 7 | interface IbLOTToken { 8 | function mint(address account, uint256 amount) external returns (bool); 9 | } 10 | 11 | contract Airdrop { 12 | 13 | using SafeMath for uint256; 14 | IbLOTToken bLotToken; 15 | PlotXToken public plotToken; 16 | address public owner; 17 | uint public endDate; 18 | uint public remainingbudget; 19 | 20 | /// @dev mapping to maintain allocated tokens to each user 21 | mapping(address => uint) public userAllocated; 22 | 23 | /// @dev mapping to maintain if user have claimed or not 24 | mapping(address => bool) public userClaimed; 25 | 26 | /** 27 | * @dev modifier that allows only the owner to execute the function 28 | */ 29 | modifier onlyOwner() { 30 | require(owner == msg.sender, "Not owner"); 31 | _; 32 | } 33 | 34 | /** 35 | * @dev Constructor 36 | * @param _plotToken The address of plot token 37 | * @param _bLotToken The address of BLot token 38 | * @param _endDate user can claim thier allocated amounts before this time. 39 | * @param _budget total amount of BLot to be minted 40 | */ 41 | constructor(address _plotToken, address _bLotToken, uint _endDate, uint _budget) public 42 | { 43 | require(_plotToken != address(0),"Can not be null address"); 44 | require(_bLotToken != address(0),"Can not be null address"); 45 | require(_endDate > now,"End date can not be past time"); 46 | plotToken = PlotXToken(_plotToken); 47 | bLotToken = IbLOTToken(_bLotToken); 48 | owner = msg.sender; 49 | endDate = _endDate; 50 | remainingbudget = _budget; 51 | plotToken.approve(address(bLotToken), _budget); 52 | } 53 | 54 | /** 55 | * @dev Allows owner to allocate Blot to user as mentioned in array. 56 | * @param _userList The user addresses. 57 | * @param _amount list of amount to be allocated to user list. 58 | */ 59 | function airdropBLot(address[] calldata _userList, uint[] calldata _amount) external onlyOwner { 60 | 61 | require(_userList.length == _amount.length,"Should have same length"); 62 | require(endDate > now, "Callable only before end date"); 63 | uint totalAmount=0; 64 | 65 | for(uint i = 0; i < _userList.length; i++) { 66 | totalAmount = totalAmount.add(_amount[i]); 67 | require(_userList[i] != address(0), "Can not be null address"); 68 | require(_amount[i] > 0, "Can not allocate 0"); 69 | require(userAllocated[_userList[i]] == 0,"Can allocate only once"); 70 | userAllocated[_userList[i]] = _amount[i]; 71 | } 72 | require(remainingbudget >= totalAmount, "Limit exceeds"); 73 | remainingbudget = remainingbudget.sub(totalAmount); 74 | } 75 | 76 | /** 77 | * @dev Allows owner to take back left over plot token after end date. 78 | */ 79 | function takeLeftOverPlot() external onlyOwner { 80 | require(endDate <= now, "Callable only after end date"); 81 | plotToken.transfer(owner, plotToken.balanceOf(address(this))); 82 | } 83 | 84 | /** 85 | * @dev Allows users to claim their allocated tokens. 86 | * user should claim before end date. 87 | */ 88 | function claim() external { 89 | require(endDate > now, "Callable only before end date"); 90 | require(!userClaimed[msg.sender], "Already claimed"); 91 | userClaimed[msg.sender] = true; 92 | bLotToken.mint(msg.sender, userAllocated[msg.sender]); 93 | } 94 | 95 | /** 96 | * @dev Allows owner to transfer ownership to other address. 97 | * @param _newOwner new owner address 98 | */ 99 | function tranferOwnership(address _newOwner) external onlyOwner { 100 | require(_newOwner != address(0), "Can not be null address"); 101 | owner = _newOwner; 102 | } 103 | 104 | } 105 | -------------------------------------------------------------------------------- /contracts/external/openzeppelin-solidity/token/ERC20/SafeERC20.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.0; 2 | 3 | import "./IERC20.sol"; 4 | import "../../math/SafeMath.sol"; 5 | import "../../utils/Address.sol"; 6 | 7 | /** 8 | * @title SafeERC20 9 | * @dev Wrappers around ERC20 operations that throw on failure (when the token 10 | * contract returns false). Tokens that return no value (and instead revert or 11 | * throw on failure) are also supported, non-reverting calls are assumed to be 12 | * successful. 13 | * To use this library you can add a `using SafeERC20 for ERC20;` statement to your contract, 14 | * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. 15 | */ 16 | library SafeERC20 { 17 | using SafeMath for uint256; 18 | using Address for address; 19 | 20 | function safeTransfer(IERC20 token, address to, uint256 value) internal { 21 | callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); 22 | } 23 | 24 | function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { 25 | callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); 26 | } 27 | 28 | function safeApprove(IERC20 token, address spender, uint256 value) internal { 29 | // safeApprove should only be called when setting an initial allowance, 30 | // or when resetting it to zero. To increase and decrease it, use 31 | // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' 32 | // solhint-disable-next-line max-line-length 33 | require((value == 0) || (token.allowance(address(this), spender) == 0), 34 | "SafeERC20: approve from non-zero to non-zero allowance" 35 | ); 36 | callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); 37 | } 38 | 39 | function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { 40 | uint256 newAllowance = token.allowance(address(this), spender).add(value); 41 | callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); 42 | } 43 | 44 | function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal { 45 | uint256 newAllowance = token.allowance(address(this), spender).sub(value, "SafeERC20: decreased allowance below zero"); 46 | callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); 47 | } 48 | 49 | /** 50 | * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement 51 | * on the return value: the return value is optional (but if data is returned, it must not be false). 52 | * @param token The token targeted by the call. 53 | * @param data The call data (encoded using abi.encode or one of its variants). 54 | */ 55 | function callOptionalReturn(IERC20 token, bytes memory data) private { 56 | // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since 57 | // we're implementing it ourselves. 58 | 59 | // A Solidity high level call has three parts: 60 | // 1. The target address is checked to verify it contains contract code 61 | // 2. The call itself is made, and success asserted 62 | // 3. The return value is decoded, which in turn checks the size of the returned data. 63 | // solhint-disable-next-line max-line-length 64 | require(address(token).isContract(), "SafeERC20: call to non-contract"); 65 | 66 | // solhint-disable-next-line avoid-low-level-calls 67 | (bool success, bytes memory returndata) = address(token).call(data); 68 | require(success, "SafeERC20: low-level call failed"); 69 | 70 | if (returndata.length > 0) { // Return data is optional 71 | // solhint-disable-next-line max-line-length 72 | require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); 73 | } 74 | } 75 | } -------------------------------------------------------------------------------- /contracts/external/uniswap/FixedPoint.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | 3 | // computes square roots using the babylonian method 4 | // https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method 5 | pragma solidity >=0.5.0; 6 | library Babylonian { 7 | function sqrt(uint y) internal pure returns (uint z) { 8 | if (y > 3) { 9 | z = y; 10 | uint x = y / 2 + 1; 11 | while (x < z) { 12 | z = x; 13 | x = (y / x + x) / 2; 14 | } 15 | } else if (y != 0) { 16 | z = 1; 17 | } 18 | // else z = 0 19 | } 20 | } 21 | 22 | library UQ112x112 { 23 | uint224 constant Q112 = 2**112; 24 | 25 | // encode a uint112 as a UQ112x112 26 | function encode(uint112 y) internal pure returns (uint224 z) { 27 | z = uint224(y) * Q112; // never overflows 28 | } 29 | 30 | // divide a UQ112x112 by a uint112, returning a UQ112x112 31 | function uqdiv(uint224 x, uint112 y) internal pure returns (uint224 z) { 32 | z = x / uint224(y); 33 | } 34 | } 35 | 36 | // a library for handling binary fixed point numbers (https://en.wikipedia.org/wiki/Q_(number_format)) 37 | library FixedPoint { 38 | // range: [0, 2**112 - 1] 39 | // resolution: 1 / 2**112 40 | struct uq112x112 { 41 | uint224 _x; 42 | } 43 | 44 | // range: [0, 2**144 - 1] 45 | // resolution: 1 / 2**112 46 | struct uq144x112 { 47 | uint _x; 48 | } 49 | 50 | uint8 private constant RESOLUTION = 112; 51 | uint private constant Q112 = uint(1) << RESOLUTION; 52 | uint private constant Q224 = Q112 << RESOLUTION; 53 | 54 | // encode a uint112 as a UQ112x112 55 | function encode(uint112 x) internal pure returns (uq112x112 memory) { 56 | return uq112x112(uint224(x) << RESOLUTION); 57 | } 58 | 59 | // encodes a uint144 as a UQ144x112 60 | function encode144(uint144 x) internal pure returns (uq144x112 memory) { 61 | return uq144x112(uint256(x) << RESOLUTION); 62 | } 63 | 64 | // divide a UQ112x112 by a uint112, returning a UQ112x112 65 | function div(uq112x112 memory self, uint112 x) internal pure returns (uq112x112 memory) { 66 | require(x != 0, 'FixedPoint: DIV_BY_ZERO'); 67 | return uq112x112(self._x / uint224(x)); 68 | } 69 | 70 | // multiply a UQ112x112 by a uint, returning a UQ144x112 71 | // reverts on overflow 72 | function mul(uq112x112 memory self, uint y) internal pure returns (uq144x112 memory) { 73 | uint z; 74 | require(y == 0 || (z = uint(self._x) * y) / y == uint(self._x), "FixedPoint: MULTIPLICATION_OVERFLOW"); 75 | return uq144x112(z); 76 | } 77 | 78 | // returns a UQ112x112 which represents the ratio of the numerator to the denominator 79 | // equivalent to encode(numerator).div(denominator) 80 | function fraction(uint112 numerator, uint112 denominator) internal pure returns (uq112x112 memory) { 81 | require(denominator > 0, "FixedPoint: DIV_BY_ZERO"); 82 | return uq112x112((uint224(numerator) << RESOLUTION) / denominator); 83 | } 84 | 85 | // decode a UQ112x112 into a uint112 by truncating after the radix point 86 | function decode(uq112x112 memory self) internal pure returns (uint112) { 87 | return uint112(self._x >> RESOLUTION); 88 | } 89 | 90 | // decode a UQ144x112 into a uint144 by truncating after the radix point 91 | function decode144(uq144x112 memory self) internal pure returns (uint144) { 92 | return uint144(self._x >> RESOLUTION); 93 | } 94 | 95 | // take the reciprocal of a UQ112x112 96 | function reciprocal(uq112x112 memory self) internal pure returns (uq112x112 memory) { 97 | require(self._x != 0, 'FixedPoint: ZERO_RECIPROCAL'); 98 | return uq112x112(uint224(Q224 / self._x)); 99 | } 100 | 101 | // square root of a UQ112x112 102 | function sqrt(uq112x112 memory self) internal pure returns (uq112x112 memory) { 103 | return uq112x112(uint224(Babylonian.sqrt(uint256(self._x)) << 56)); 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /contracts/external/lockable-token/IERC1132.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.5.7; 2 | 3 | /** 4 | * @title ERC1132 interface 5 | * @dev see https://github.com/ethereum/EIPs/issues/1132 6 | */ 7 | 8 | contract IERC1132 { 9 | /** 10 | * @dev Reasons why a user's tokens have been locked 11 | */ 12 | mapping(address => bytes32[]) public lockReason; 13 | 14 | /** 15 | * @dev locked token structure 16 | */ 17 | struct LockToken { 18 | uint256 amount; 19 | uint256 validity; 20 | bool claimed; 21 | } 22 | 23 | /** 24 | * @dev Holds number & validity of tokens locked for a given reason for 25 | * a specified address 26 | */ 27 | mapping(address => mapping(bytes32 => LockToken)) public locked; 28 | 29 | /** 30 | * @dev Records data of all the tokens Locked 31 | */ 32 | event Locked( 33 | address indexed _of, 34 | bytes32 indexed _reason, 35 | uint256 _amount, 36 | uint256 _validity 37 | ); 38 | 39 | /** 40 | * @dev Records data of all the tokens unlocked 41 | */ 42 | event Unlocked( 43 | address indexed _of, 44 | bytes32 indexed _reason, 45 | uint256 _amount 46 | ); 47 | 48 | /** 49 | * @dev Locks a specified amount of tokens against an address, 50 | * for a specified reason and time 51 | * @param _reason The reason to lock tokens 52 | * @param _amount Number of tokens to be locked 53 | * @param _time Lock time in seconds 54 | */ 55 | function lock(bytes32 _reason, uint256 _amount, uint256 _time) 56 | public returns (bool); 57 | 58 | /** 59 | * @dev Returns tokens locked for a specified address for a 60 | * specified reason 61 | * 62 | * @param _of The address whose tokens are locked 63 | * @param _reason The reason to query the lock tokens for 64 | */ 65 | function tokensLocked(address _of, bytes32 _reason) 66 | public view returns (uint256 amount); 67 | 68 | /** 69 | * @dev Returns tokens locked for a specified address for a 70 | * specified reason at a specific time 71 | * 72 | * @param _of The address whose tokens are locked 73 | * @param _reason The reason to query the lock tokens for 74 | * @param _time The timestamp to query the lock tokens for 75 | */ 76 | function tokensLockedAtTime(address _of, bytes32 _reason, uint256 _time) 77 | public view returns (uint256 amount); 78 | 79 | /** 80 | * @dev Returns total tokens held by an address (locked + transferable) 81 | * @param _of The address to query the total balance of 82 | */ 83 | function totalBalanceOf(address _of) 84 | public view returns (uint256 amount); 85 | 86 | /** 87 | * @dev Extends lock for a specified reason and time 88 | * @param _reason The reason to lock tokens 89 | * @param _time Lock extension time in seconds 90 | */ 91 | function extendLock(bytes32 _reason, uint256 _time) 92 | public returns (bool); 93 | 94 | /** 95 | * @dev Increase number of tokens locked for a specified reason 96 | * @param _reason The reason to lock tokens 97 | * @param _amount Number of tokens to be increased 98 | */ 99 | function increaseLockAmount(bytes32 _reason, uint256 _amount) 100 | public returns (bool); 101 | 102 | /** 103 | * @dev Returns unlockable tokens for a specified address for a specified reason 104 | * @param _of The address to query the the unlockable token count of 105 | * @param _reason The reason to query the unlockable tokens for 106 | */ 107 | function tokensUnlockable(address _of, bytes32 _reason) 108 | public view returns (uint256 amount); 109 | 110 | /** 111 | * @dev Unlocks the unlockable tokens of a specified address 112 | * @param _of Address of user, claiming back unlockable tokens 113 | */ 114 | function unlock(address _of) 115 | public returns (uint256 unlockableTokens); 116 | 117 | /** 118 | * @dev Gets the unlockable tokens of a specified address 119 | * @param _of The address to query the the unlockable token count of 120 | */ 121 | function getUnlockableTokens(address _of) 122 | public view returns (uint256 unlockableTokens); 123 | 124 | } -------------------------------------------------------------------------------- /test/22_blottoken.js: -------------------------------------------------------------------------------- 1 | const BLOT = artifacts.require('BLOT'); 2 | const PLOT = artifacts.require('MockPLOT'); 3 | const OwnedUpgradeabilityProxy = artifacts.require("OwnedUpgradeabilityProxy"); 4 | const Master = artifacts.require("Master"); 5 | const ZERO_ADDRESS = "0x0000000000000000000000000000000000000000"; 6 | const { assertRevert } = require('./utils/assertRevert'); 7 | var BLOTInstance; 8 | contract('bLOTToken', function([user1,user2]){ 9 | 10 | 11 | it('1.Minter can mint bLOTTokens',async function(){ 12 | let masterInstance = await OwnedUpgradeabilityProxy.deployed(); 13 | masterInstance = await Master.at(masterInstance.address); 14 | PLOTInstance = await PLOT.deployed(); 15 | BLOTInstance = await BLOT.at(await masterInstance.getLatestAddress(web3.utils.fromAscii("BL"))); 16 | await PLOTInstance.approve(BLOTInstance.address, "10000000000000000000000"); 17 | let canMint = await BLOTInstance.mint(user1,"1000000000000000000000"); 18 | await assertRevert(BLOTInstance.setMasterAddress()); 19 | assert.ok(canMint) 20 | }) 21 | 22 | 23 | it('2. Should reduce PLOT tokens to give equal number of bLOT tokens',async function(){ 24 | PLOTInstance = await PLOT.deployed(); 25 | // BLOTInstance = await BLOT.deployed(); 26 | await PLOTInstance.approve(BLOTInstance.address, "10000000000000000000000"); 27 | let PLOTbeforeUser1 = await PLOTInstance.balanceOf(user1); 28 | let BLOTbeforeUser2 = await BLOTInstance.balanceOf(user2); 29 | await BLOTInstance.mint(user2,"1000000000000000000000"); 30 | let PLOTAfterUser1 = await PLOTInstance.balanceOf(user1); 31 | let BLOTAfterUser2 = await BLOTInstance.balanceOf(user2); 32 | // assert.equal(BLOTAfterUser2/1,PLOTbeforeUser1/1-PLOTAfterUser1/1) 33 | }) 34 | 35 | 36 | it('3. Totalsupply of PLOT tokens to remain same ,Total supply of bLOT should increase',async function(){ 37 | PLOTInstance = await PLOT.deployed(); 38 | // BLOTInstance = await BLOT.deployed(); 39 | await PLOTInstance.approve(BLOTInstance.address, "10000000000000000000000"); 40 | let totalSupplyPLOT1 = await PLOTInstance.totalSupply(); 41 | let totalSupplyBLOT1 = await BLOTInstance.totalSupply(); 42 | await BLOTInstance.mint(user2,"1000000000000000000000"); 43 | let totalSupplyPLOT2 = await PLOTInstance.totalSupply(); 44 | let totalSupplyBLOT2 = await BLOTInstance.totalSupply(); 45 | assert.equal(totalSupplyPLOT1/1,totalSupplyPLOT2/1) 46 | assert.equal(totalSupplyBLOT2/1-totalSupplyBLOT1/1,"1000000000000000000000") 47 | }) 48 | 49 | 50 | it('4. Minter can transfer bLOT tokens ,non minter cannot transfer bLOT token',async function(){ 51 | PLOTInstance = await PLOT.deployed(); 52 | // BLOTInstance = await BLOT.deployed(); 53 | await PLOTInstance.approve(BLOTInstance.address, "10000000000000000000000"); 54 | await BLOTInstance.mint(user1,"1000000000000000000000"); 55 | let canTransfer = await BLOTInstance.transfer(user2,"100000000000000000",{from : user1}); 56 | assert.ok(canTransfer) 57 | await assertRevert(BLOTInstance.transfer(user2,"100000000000000000",{from : user2})) 58 | }) 59 | 60 | 61 | it('5. Minter can transfer from bLOT tokens ,non minter cannot transfer from bLOT token',async function(){ 62 | PLOTInstance = await PLOT.deployed(); 63 | // BLOTInstance = await BLOT.deployed(); 64 | await PLOTInstance.approve(BLOTInstance.address, "10000000000000000000000"); 65 | await BLOTInstance.mint(user1,"1000000000000000000000") 66 | }) 67 | 68 | 69 | it('6. bLOT tokens cannot be converted to PLOT directly',async function(){ 70 | PLOTInstance = await PLOT.deployed(); 71 | // BLOTInstance = await BLOT.deployed(); 72 | await PLOTInstance.approve(BLOTInstance.address, "10000000000000000000000"); 73 | await BLOTInstance.mint(user1,"1000000000000000000000"); 74 | await assertRevert(BLOTInstance.convertToPLOT(BLOTInstance.address, BLOTInstance.address, "10000000000000000000000")) 75 | }) 76 | 77 | it('7. Should not allow to mint to zero address',async function(){ 78 | await PLOTInstance.approve(BLOTInstance.address, "10000000000000000000000"); 79 | await assertRevert(BLOTInstance.mint(ZERO_ADDRESS,"1000000000000000000000")); 80 | }) 81 | 82 | it('8. Should not allow to re-initiate bLOT instance', async function() { 83 | await assertRevert(BLOTInstance.initiatebLOT(user1)); 84 | }); 85 | }) 86 | 87 | -------------------------------------------------------------------------------- /truffle-config.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Use this file to configure your truffle project. It's seeded with some 3 | * common settings for different networks and features like migrations, 4 | * compilation and testing. Uncomment the ones you need or modify 5 | * them to suit your project as necessary. 6 | * 7 | * More information about configuration can be found at: 8 | * 9 | * truffleframework.com/docs/advanced/configuration 10 | * 11 | * To deploy via Infura you'll need a wallet provider (like truffle-hdwallet-provider) 12 | * to sign your transactions before they're sent to a remote public node. Infura accounts 13 | * are available for free at: infura.io/register. 14 | * 15 | * You'll also need a mnemonic - the twelve word phrase the wallet uses to generate 16 | * public/private key pairs. If you're publishing your code to GitHub make sure you load this 17 | * phrase from a file you've .gitignored so it doesn't accidentally become public. 18 | * 19 | */ 20 | 21 | // const HDWalletProvider = require('truffle-hdwallet-provider'); 22 | // const infuraKey = "fj4jll3k....."; 23 | // 24 | // const fs = require('fs'); 25 | // const mnemonic = fs.readFileSync(".secret").toString().trim(); 26 | 27 | module.exports = { 28 | /** 29 | * Networks define how you connect to your ethereum client and let you set the 30 | * defaults web3 uses to send transactions. If you don't specify one truffle 31 | * will spin up a development blockchain for you on port 9545 when you 32 | * run `develop` or `test`. You can ask a truffle command to use a specific 33 | * network from the command line, e.g 34 | * 35 | * $ truffle test --network