diff --git a/src/masternodes/rpc_accounts.cpp b/src/masternodes/rpc_accounts.cpp index 618e2c0470..9840c289a2 100644 --- a/src/masternodes/rpc_accounts.cpp +++ b/src/masternodes/rpc_accounts.cpp @@ -1810,6 +1810,7 @@ UniValue getburninfo(const JSONRPCRequest& request) { CBalances burntTokens; CBalances consortiumTokens; + CBalances nonConsortiumTokens; CBalances dexfeeburn; CBalances paybackfees; CBalances paybackFee; @@ -1905,7 +1906,7 @@ UniValue getburninfo(const JSONRPCRequest& request) { if (value.category == uint8_t(CustomTxType::BurnToken)) { for (auto const & diff : value.diff) { - consortiumTokens.Add({diff.first, diff.second}); + nonConsortiumTokens.Add({diff.first, diff.second}); } return true; } @@ -1919,6 +1920,19 @@ UniValue getburninfo(const JSONRPCRequest& request) { burnView->ForEachAccountHistory(calculateBurnAmounts); + CDataStructureV0 liveKey = {AttributeTypes::Live, ParamIDs::Economy, EconomyKeys::ConsortiumMinted}; + auto balances = attributes->GetValue(liveKey, CConsortiumGlobalMinted{}); + + for (auto const & token: nonConsortiumTokens.balances) + { + TAmounts amount; + amount[token.first] = balances[token.first].burnt; + consortiumTokens.AddBalances(amount); + } + + nonConsortiumTokens.SubBalances(consortiumTokens.balances); + burntTokens.AddBalances(nonConsortiumTokens.balances); + UniValue result(UniValue::VOBJ); result.pushKV("address", ScriptToString(burnAddress)); result.pushKV("amount", ValueFromAmount(burntDFI)); diff --git a/src/masternodes/rpc_tokens.cpp b/src/masternodes/rpc_tokens.cpp index e6112ce409..4dc9a9bf07 100644 --- a/src/masternodes/rpc_tokens.cpp +++ b/src/masternodes/rpc_tokens.cpp @@ -805,7 +805,7 @@ UniValue burntokens(const JSONRPCRequest& request) { {"metadata", RPCArg::Type::OBJ, RPCArg::Optional::NO, "", { {"amounts", RPCArg::Type::STR, RPCArg::Optional::NO, "Amount as json string, or array. Example: '[ \"amount@token\" ]'"}, - {"from", RPCArg::Type::STR, RPCArg::Optional::NO, "Address containing tokens to be burned."}, + {"from", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "Address containing tokens to be burned."}, {"context", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "Additional data necessary for specific burn type"}, } }, @@ -841,18 +841,43 @@ UniValue burntokens(const JSONRPCRequest& request) { CBurnTokensMessage burnedTokens; UniValue metaObj = request.params[0].get_obj(); + burnedTokens.burnType = CBurnTokensMessage::BurnType::TokenBurn; + if (!metaObj["amounts"].isNull()) burnedTokens.amounts = DecodeAmounts(pwallet->chain(), metaObj["amounts"].getValStr(), ""); else - throw JSONRPCError(RPC_INVALID_PARAMETER,"Invalid parameters, argument \"amounts\" must not be null"); - if (!metaObj["from"].isNull()) - burnedTokens.from = DecodeScript(metaObj["from"].getValStr()); - else - throw JSONRPCError(RPC_INVALID_PARAMETER,"Invalid parameters, argument \"from\" must not be null"); + throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameters, argument \"amounts\" must not be null"); + + if (burnedTokens.amounts.balances.size() == 1 && metaObj["from"].isNull() && metaObj["context"].isNull()) { + auto attributes = pcustomcsview->GetAttributes(); + + if (attributes) { + CDataStructureV0 enableKey{AttributeTypes::Param, ParamIDs::Feature, DFIPKeys::ConsortiumEnabled}; + if (attributes->GetValue(enableKey, false)) { + CDataStructureV0 membersKey{AttributeTypes::Consortium, + burnedTokens.amounts.balances.begin()->first.v, + ConsortiumKeys::MemberValues}; + auto members = attributes->GetValue(membersKey, CConsortiumMembers{}); + + for (const auto &member : members) { + if (IsMineCached(*pwallet, member.second.ownerAddress)) { + burnedTokens.from = member.second.ownerAddress; + break; + } + } + } + } + if (burnedTokens.from.empty()) + throw JSONRPCError(RPC_INVALID_PARAMETER, "No valid addresses could be found, use the \"from\" argument to set address to burn from"); + } else { + if (!metaObj["from"].isNull()) + burnedTokens.from = DecodeScript(metaObj["from"].getValStr()); + else + throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameters, argument \"from\" must not be null"); - burnedTokens.burnType = CBurnTokensMessage::BurnType::TokenBurn; - if (!metaObj["context"].isNull()) - burnedTokens.context = DecodeScript(metaObj["context"].getValStr()); + if (!metaObj["context"].isNull()) + burnedTokens.context = DecodeScript(metaObj["context"].getValStr()); + } UniValue const & txInputs = request.params[2]; diff --git a/test/functional/feature_consortium.py b/test/functional/feature_consortium.py index e3aa657503..0aa3180897 100644 --- a/test/functional/feature_consortium.py +++ b/test/functional/feature_consortium.py @@ -54,6 +54,8 @@ def run_test(self): self.nodes[0].generate(1) self.sync_blocks() + self.nodes[0].minttokens(["2@" + symbolBTC]) + self.nodes[0].createtoken({ "symbol": symbolDOGE, "name": "DOGE token", @@ -217,10 +219,15 @@ def run_test(self): assert_equal(attribs['v0/live/economy/consortium_members/2/01/supply'], Decimal('2.00000000')) assert_raises_rpc_error(-32600, "You will exceed your maximum mint limit for " + symbolDOGE + " token by minting this amount!", self.nodes[2].minttokens, ["3.00000001@" + symbolDOGE]) + assert_raises_rpc_error(-8, "No valid addresses could be found, use the \"from\" argument to set address to burn from", self.nodes[0].burntokens, {'amounts': "1.00000000@" + symbolBTC}) + + self.nodes[0].burntokens({ + 'amounts': "2@" + symbolBTC, + 'from': account0, + }) self.nodes[2].burntokens({ 'amounts': "1@" + symbolDOGE, - 'from': account2, }) self.nodes[2].generate(1) @@ -314,7 +321,7 @@ def run_test(self): attribs = self.nodes[0].getgov('ATTRIBUTES')['ATTRIBUTES'] assert_equal(attribs['v0/consortium/' + idDOGE + '/members'], {"01":{"name":"account2DOGE","ownerAddress": account2,"backingId":"ebf634ef7143bc5466995a385b842649b2037ea89d04d469bfa5ec29daf7d1cf","mintLimit":Decimal('5.00000000'),"mintLimitDaily":Decimal('5.00000000'),"status":1},"02":{"name":"account1DOGE","ownerAddress": account1,"backingId":"ebf634ef7143bc5466995a385b842649b2037ea89d04d469bfa5ec29daf7d1cf","mintLimit":Decimal('5.00000000'),"mintLimitDaily":Decimal('5.00000000'),"status":0}}) - assert_equal(self.nodes[0].getburninfo(), {'address': 'mfburnZSAM7Gs1hpDeNaMotJXSGA7edosG', 'amount': Decimal('0E-8'), 'tokens': [], 'consortiumtokens': ['2.00000000@DOGE'], 'feeburn': Decimal('2.00000000'), 'auctionburn': Decimal('0E-8'), 'paybackburn': [], 'dexfeetokens': [], 'dfipaybackfee': Decimal('0E-8'), 'dfipaybacktokens': [], 'paybackfees': [], 'paybacktokens': [], 'emissionburn': Decimal('4923.76500000'), 'dfip2203': [], 'dfip2206f': []}) + assert_equal(self.nodes[0].getburninfo(), {'address': 'mfburnZSAM7Gs1hpDeNaMotJXSGA7edosG', 'amount': Decimal('0E-8'), 'tokens': ['2.00000000@BTC', '0.50000000@DOGE'], 'consortiumtokens': ['1.50000000@DOGE'], 'feeburn': Decimal('2.00000000'), 'auctionburn': Decimal('0E-8'), 'paybackburn': [], 'dexfeetokens': [], 'dfipaybackfee': Decimal('0E-8'), 'dfipaybacktokens': [], 'paybackfees': [], 'paybacktokens': [], 'emissionburn': Decimal('4923.76500000'), 'dfip2203': [], 'dfip2206f': []}) assert_raises_rpc_error(-32600, "Cannot mint token, not an active member of consortium for DOGE!", self.nodes[2].minttokens, ["1@" + symbolDOGE]) @@ -330,7 +337,6 @@ def run_test(self): # burn to check that total minted is checked against max limit self.nodes[2].burntokens({ 'amounts': "6@" + symbolBTC, - 'from': account2, }) self.nodes[2].generate(1) self.sync_blocks() @@ -418,6 +424,7 @@ def run_test(self): assert_raises_rpc_error(-32600, "You will exceed your daily mint limit for " + symbolBTC + " token by minting this amount", self.nodes[3].minttokens, ["1@" + symbolBTC]) # burn to check that burning from address of a member for different token does not get counted when burning other tokens + assert_raises_rpc_error(-8, "No valid addresses could be found, use the \"from\" argument to set address to burn from", self.nodes[1].burntokens, {'amounts': "0.10000000@" + symbolBTC}) self.nodes[1].burntokens({ 'amounts': "0.1@" + symbolBTC, 'from': account1, @@ -526,6 +533,8 @@ def run_test(self): assert_raises_rpc_error(-5, "Amount must be positive or -1", self.nodes[0].setgov, { "ATTRIBUTES": {'v0/consortium/' + idBTC + '/mint_limit': '-2'}}) + assert_equal(self.nodes[0].getburninfo(), {'address': 'mfburnZSAM7Gs1hpDeNaMotJXSGA7edosG', 'amount': Decimal('0E-8'), 'tokens': ['2.10000000@BTC', '0.50000000@DOGE'], 'consortiumtokens': ['6.10000000@BTC', '1.50000000@DOGE'], 'feeburn': Decimal('2.00000000'), 'auctionburn': Decimal('0E-8'), 'paybackburn': [], 'dexfeetokens': [], 'dfipaybackfee': Decimal('0E-8'), 'dfipaybacktokens': [], 'paybackfees': [], 'paybacktokens': [], 'emissionburn': Decimal('5386.81500000'), 'dfip2203': [], 'dfip2206f': []}) + # Price feeds price_feed = [ {"currency": "USD", "token": "TSLA"},