diff --git a/contracts/mining.js b/contracts/mining.js index 88bbdbe0..85e5da7f 100644 --- a/contracts/mining.js +++ b/contracts/mining.js @@ -223,7 +223,7 @@ actions.updatePool = async (payload) => { // eslint-disable-next-line no-template-curly-in-string const utilityTokenBalance = await api.db.findOneInTable('tokens', 'balances', { account: api.sender, symbol: "'${CONSTANTS.UTILITY_TOKEN_SYMBOL}$'" }); - const authorized = api.BigNumber(poolUpdateFee).lte(0) + const authorized = api.BigNumber(poolUpdateFee).lte(0) || api.sender === api.owner ? true : utilityTokenBalance && api.BigNumber(utilityTokenBalance.balance).gte(poolUpdateFee); @@ -236,7 +236,8 @@ actions.updatePool = async (payload) => { const pool = await api.db.findOne('pools', { id }); if (api.assert(pool, 'pool id not found')) { const minedTokenObject = await api.db.findOneInTable('tokens', 'tokens', { symbol: pool.minedToken }); - if (api.assert(minedTokenObject && minedTokenObject.issuer === api.sender, 'must be issuer of minedToken') + // eslint-disable-next-line no-template-curly-in-string + if (api.assert(minedTokenObject && (minedTokenObject.issuer === api.sender || (minedTokenObject.symbol === "'${CONSTANTS.UTILITY_TOKEN_SYMBOL}$'" && api.sender === api.owner)), 'must be issuer of minedToken') && api.assert(api.BigNumber(lotteryAmount).dp() <= minedTokenObject.precision, 'minedToken precision mismatch for lotteryAmount')) { const validMinersChange = validateTokenMinersChange(pool.tokenMiners, tokenMiners); if (validMinersChange) { @@ -259,7 +260,7 @@ actions.updatePool = async (payload) => { await api.db.update('pools', pool); // burn the token creation fees - if (api.BigNumber(poolUpdateFee).gt(0)) { + if (api.sender !== api.owner && api.BigNumber(poolUpdateFee).gt(0)) { await api.executeSmartContract('tokens', 'transfer', { // eslint-disable-next-line no-template-curly-in-string to: 'null', symbol: "'${CONSTANTS.UTILITY_TOKEN_SYMBOL}$'", quantity: poolUpdateFee, isSignedWithActiveKey, @@ -291,7 +292,7 @@ actions.createPool = async (payload) => { // eslint-disable-next-line no-template-curly-in-string const utilityTokenBalance = await api.db.findOneInTable('tokens', 'balances', { account: api.sender, symbol: "'${CONSTANTS.UTILITY_TOKEN_SYMBOL}$'" }); - const authorizedCreation = api.BigNumber(poolCreationFee).lte(0) + const authorizedCreation = api.BigNumber(poolCreationFee).lte(0) || api.sender === api.owner ? true : utilityTokenBalance && api.BigNumber(utilityTokenBalance.balance).gte(poolCreationFee); @@ -306,7 +307,8 @@ actions.createPool = async (payload) => { const minedTokenObject = await api.db.findOneInTable('tokens', 'tokens', { symbol: minedToken }); if (api.assert(minedTokenObject, 'minedToken does not exist') - && api.assert(minedTokenObject.issuer === api.sender, 'must be issuer of minedToken') + // eslint-disable-next-line no-template-curly-in-string + && api.assert(minedTokenObject.issuer === api.sender || (minedTokenObject.symbol === "'${CONSTANTS.UTILITY_TOKEN_SYMBOL}$'" && api.sender === api.owner), 'must be issuer of minedToken') && api.assert(api.BigNumber(lotteryAmount).dp() <= minedTokenObject.precision, 'minedToken precision mismatch for lotteryAmount') && await validateTokenMiners(tokenMiners)) { const blockDate = new Date(`${api.hiveBlockTimestamp}.000Z`); @@ -337,7 +339,7 @@ actions.createPool = async (payload) => { await api.db.insert('pools', newPool); // burn the token creation fees - if (api.BigNumber(poolCreationFee).gt(0)) { + if (api.sender !== api.owner && api.BigNumber(poolCreationFee).gt(0)) { await api.executeSmartContract('tokens', 'transfer', { // eslint-disable-next-line no-template-curly-in-string to: 'null', symbol: "'${CONSTANTS.UTILITY_TOKEN_SYMBOL}$'", quantity: poolCreationFee, isSignedWithActiveKey, diff --git a/test/mining.js b/test/mining.js index 6c0d2f9d..187a622c 100644 --- a/test/mining.js +++ b/test/mining.js @@ -850,6 +850,64 @@ describe('mining', function () { }); }); + it('should update mining pool for utility token as api owner', (done) => { + new Promise(async (resolve) => { + await loadPlugin(blockchain); + database1 = new Database(); + + await database1.init(conf.databaseURL, conf.databaseName); + + let transactions = []; + transactions.push(new Transaction(12345678901, getNextTxId(), CONSTANTS.HIVE_ENGINE_ACCOUNT, 'contract', 'update', JSON.stringify(tokensContractPayload))); + transactions.push(new Transaction(12345678901, getNextTxId(), CONSTANTS.HIVE_ENGINE_ACCOUNT, 'contract', 'deploy', JSON.stringify(contractPayload))); + transactions.push(new Transaction(12345678901, getNextTxId(), CONSTANTS.HIVE_ENGINE_ACCOUNT, 'mining', 'createPool', `{ "lotteryWinners": 1, "lotteryIntervalHours": 720, "lotteryAmount": "1", "minedToken": "${CONSTANTS.UTILITY_TOKEN_SYMBOL}", "tokenMiners": [{"symbol": "${CONSTANTS.UTILITY_TOKEN_SYMBOL}", "multiplier": 1}], "isSignedWithActiveKey": true }`)); + + let block = { + refHiveBlockNumber: 12345678901, + refHiveBlockId: 'ABCD1', + prevRefHiveBlockId: 'ABCD2', + timestamp: '2018-06-01T00:00:00', + transactions, + }; + + await send(blockchain.PLUGIN_NAME, 'MASTER', { action: blockchain.PLUGIN_ACTIONS.PRODUCE_NEW_BLOCK_SYNC, payload: block }); + + await assertNoErrorInLastBlock(); + + await assertTokenPool(CONSTANTS.UTILITY_TOKEN_SYMBOL, `${CONSTANTS.UTILITY_TOKEN_SYMBOL}:${CONSTANTS.UTILITY_TOKEN_SYMBOL}`); + await assertPool({id: `${CONSTANTS.UTILITY_TOKEN_SYMBOL}:${CONSTANTS.UTILITY_TOKEN_SYMBOL}`, totalPower: '0', lotteryWinners: 1, lotteryIntervalHours: 720, lotteryAmount: "1", nextLotteryTimestamp: new Date('2018-07-01T00:00:00.000Z').getTime()}, { inProgress: false, lastAccountId: 0, tokenIndex: 0 }); + await assertUserBalances(CONSTANTS.HIVE_ENGINE_ACCOUNT, CONSTANTS.UTILITY_TOKEN, '1500011.41552511', 0); + + transactions = []; + transactions.push(new Transaction(12345678903, getNextTxId(), CONSTANTS.HIVE_ENGINE_ACCOUNT, 'mining', 'updatePool', `{ "id": "${CONSTANTS.UTILITY_TOKEN_SYMBOL}:${CONSTANTS.UTILITY_TOKEN_SYMBOL}", "lotteryWinners": 2, "lotteryIntervalHours": 3, "lotteryAmount": "15.7", "minedToken": "${CONSTANTS.UTILITY_TOKEN_SYMBOL}", "tokenMiners": [{"symbol": "${CONSTANTS.UTILITY_TOKEN_SYMBOL}", "multiplier": 1}], "isSignedWithActiveKey": true }`)); + + block = { + refHiveBlockNumber: 12345678903, + refHiveBlockId: 'ABCD1', + prevRefHiveBlockId: 'ABCD2', + timestamp: '2018-06-01T00:00:00', + transactions, + }; + + await send(blockchain.PLUGIN_NAME, 'MASTER', { action: blockchain.PLUGIN_ACTIONS.PRODUCE_NEW_BLOCK_SYNC, payload: block }); + + await assertNoErrorInLastBlock(); + + await assertTokenPool(CONSTANTS.UTILITY_TOKEN_SYMBOL, `${CONSTANTS.UTILITY_TOKEN_SYMBOL}:${CONSTANTS.UTILITY_TOKEN_SYMBOL}`); + + await assertPool({id: `${CONSTANTS.UTILITY_TOKEN_SYMBOL}:${CONSTANTS.UTILITY_TOKEN_SYMBOL}`, totalPower: '0', lotteryWinners: 2, lotteryIntervalHours: 3, lotteryAmount: "15.7", nextLotteryTimestamp: new Date('2018-06-01T03:00:00.000Z').getTime()}, { inProgress: false, lastAccountId: 0, tokenIndex: 0 }); + + await assertUserBalances(CONSTANTS.HIVE_ENGINE_ACCOUNT, CONSTANTS.UTILITY_TOKEN, '1500011.41552511', 0); + + resolve(); + }) + .then(() => { + unloadPlugin(blockchain); + database1.close(); + done(); + }); + }); + it('should not run basic lottery when inactive', (done) => { new Promise(async (resolve) => { await loadPlugin(blockchain);