Skip to content

Commit

Permalink
DFIP2203 minted category and txn numbering (#1177)
Browse files Browse the repository at this point in the history
* DFIP2203 add minted category to Govs

* Unique TXN for each entry

* Increment minted tokens on future swap execution

Co-authored-by: Prasanna Loganathar <pvl@prasannavl.com>
  • Loading branch information
Bushstar and prasannavl committed Mar 31, 2022
1 parent 1a93ddf commit 35ad71b
Show file tree
Hide file tree
Showing 13 changed files with 159 additions and 96 deletions.
2 changes: 1 addition & 1 deletion src/interfaces/chain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,7 @@ class ChainImpl : public Chain
LOCK(cs_main);
return pcustomcsview->GetMasternode(nodeId);
}
std::unique_ptr<CToken> existTokenGuessId(const std::string & str, DCT_ID & id) const override
boost::optional<CTokensView::CTokenImpl> existTokenGuessId(const std::string & str, DCT_ID & id) const override
{
LOCK(cs_main);
return pcustomcsview->GetTokenGuessId(str, id);
Expand Down
4 changes: 2 additions & 2 deletions src/interfaces/chain.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ class CFeeRate;
class CMasternode;
class CRPCCommand;
class CScheduler;
class CToken;
class CTokenImplementation;
class CValidationState;
class Coin;
class uint256;
Expand Down Expand Up @@ -152,7 +152,7 @@ class Chain

virtual bool mnCanSpend(const uint256 & nodeId, int height) const = 0;
virtual boost::optional<CMasternode> mnExists(const uint256 & nodeId) const = 0;
virtual std::unique_ptr<CToken> existTokenGuessId(const std::string & str, DCT_ID & id) const = 0;
virtual boost::optional<CTokenImplementation> existTokenGuessId(const std::string & str, DCT_ID & id) const = 0;

//! Estimate fraction of total transactions verified if blocks up to
//! the specified block hash are verified.
Expand Down
20 changes: 12 additions & 8 deletions src/masternodes/govvariables/attributes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@ const std::map<uint8_t, std::map<uint8_t, std::string>>& ATTRIBUTES::displayKeys
{EconomyKeys::PaybackDFITokens, "dfi_payback_tokens"},
{EconomyKeys::DFIP2203Current, "dfip2203_current"},
{EconomyKeys::DFIP2203Burned, "dfip2203_burned"},
{EconomyKeys::DFIP2203Minted, "dfip2203_minted"},
}
},
};
Expand Down Expand Up @@ -396,31 +397,34 @@ Res ATTRIBUTES::RefundFuturesContracts(CCustomCSView &mnview, const uint32_t hei
CDataStructureV0 liveKey{AttributeTypes::Live, ParamIDs::Economy, EconomyKeys::DFIP2203Current};
auto balances = GetValue(liveKey, CBalances{});


CHistoryWriters writers{paccountHistoryDB.get(), nullptr, nullptr};
CAccountsHistoryWriter view(mnview, height, ~0u, {}, uint8_t(CustomTxType::FutureSwapRefund), &writers);
auto txn = std::numeric_limits<uint32_t>::max();

for (const auto& [key, value] : userFuturesValues) {
view.EraseFuturesUserValues(key);

auto res = view.SubBalance(*contractAddressValue, value.source);
mnview.EraseFuturesUserValues(key);

CHistoryWriters subWriters{paccountHistoryDB.get(), nullptr, nullptr};
CAccountsHistoryWriter subView(mnview, height, txn--, {}, uint8_t(CustomTxType::FutureSwapRefund), &subWriters);
auto res = subView.SubBalance(*contractAddressValue, value.source);
if (!res) {
return res;
}
subView.Flush();

res = view.AddBalance(key.owner, value.source);
CHistoryWriters addWriters{paccountHistoryDB.get(), nullptr, nullptr};
CAccountsHistoryWriter addView(mnview, height, txn--, {}, uint8_t(CustomTxType::FutureSwapRefund), &addWriters);
res = addView.AddBalance(key.owner, value.source);
if (!res) {
return res;
}
addView.Flush();

res = balances.Sub(value.source);
if (!res) {
return res;
}
}

view.Flush();

attributes[liveKey] = balances;

return Res::Ok();
Expand Down
1 change: 1 addition & 0 deletions src/masternodes/govvariables/attributes.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ enum EconomyKeys : uint8_t {
PaybackTokens = 'b',
DFIP2203Current = 'c',
DFIP2203Burned = 'd',
DFIP2203Minted = 'e',
};

enum DFIPKeys : uint8_t {
Expand Down
23 changes: 12 additions & 11 deletions src/masternodes/mn_checks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1095,24 +1095,25 @@ class CCustomTxApplyVisitor : public CCustomTxVisitor
Res operator()(const CMintTokensMessage& obj) const {
// check auth and increase balance of token's owner
for (const auto& kv : obj.balances) {
DCT_ID tokenId = kv.first;
const DCT_ID& tokenId = kv.first;

auto token = mnview.GetToken(kv.first);
auto token = mnview.GetToken(tokenId);
if (!token) {
return Res::Err("token %s does not exist!", tokenId.ToString());
}
auto tokenImpl = static_cast<const CTokenImplementation&>(*token);

auto mintable = MintableToken(tokenId, tokenImpl);
auto mintable = MintableToken(tokenId, *token);
if (!mintable) {
return std::move(mintable);
}
auto minted = mnview.AddMintedTokens(tokenImpl.creationTx, kv.second);

auto minted = mnview.AddMintedTokens(tokenId, kv.second);
if (!minted) {
return minted;
}

CalculateOwnerRewards(*mintable.val);
auto res = mnview.AddBalance(*mintable.val, CTokenAmount{kv.first, kv.second});
auto res = mnview.AddBalance(*mintable.val, CTokenAmount{tokenId, kv.second});
if (!res) {
return res;
}
Expand Down Expand Up @@ -2786,7 +2787,7 @@ class CCustomTxApplyVisitor : public CCustomTxVisitor
{
if (auto collaterals = mnview.GetVaultCollaterals(obj.vaultId))
{
boost::optional<std::pair<DCT_ID, std::unique_ptr<CToken>>> tokenDUSD;
boost::optional<std::pair<DCT_ID, boost::optional<CTokensView::CTokenImpl>>> tokenDUSD;
if (static_cast<int>(height) >= consensus.FortCanningRoadHeight) {
tokenDUSD = mnview.GetToken("DUSD");
}
Expand Down Expand Up @@ -2852,7 +2853,7 @@ class CCustomTxApplyVisitor : public CCustomTxVisitor
uint64_t totalLoansActivePrice = 0, totalLoansNextPrice = 0;
for (const auto& kv : obj.amounts.balances)
{
DCT_ID tokenId = kv.first;
const DCT_ID& tokenId = kv.first;
auto loanToken = mnview.GetLoanTokenByID(tokenId);
if (!loanToken)
return Res::Err("Loan token with id (%s) does not exist!", tokenId.ToString());
Expand Down Expand Up @@ -2892,7 +2893,7 @@ class CCustomTxApplyVisitor : public CCustomTxVisitor
return Res::Err("Exceed maximum loans");
}

res = mnview.AddMintedTokens(loanToken->creationTx, kv.second);
res = mnview.AddMintedTokens(tokenId, kv.second);
if (!res)
return res;

Expand All @@ -2904,7 +2905,7 @@ class CCustomTxApplyVisitor : public CCustomTxVisitor
return res;
}

boost::optional<std::pair<DCT_ID, std::unique_ptr<CToken>>> tokenDUSD;
boost::optional<std::pair<DCT_ID, boost::optional<CTokensView::CTokenImpl>>> tokenDUSD;
if (static_cast<int>(height) >= consensus.FortCanningRoadHeight) {
tokenDUSD = mnview.GetToken("DUSD");
}
Expand Down Expand Up @@ -3118,7 +3119,7 @@ class CCustomTxApplyVisitor : public CCustomTxVisitor

if (paybackTokenId == loanTokenId)
{
res = mnview.SubMintedTokens(loanToken->creationTx, subLoan);
res = mnview.SubMintedTokens(loanTokenId, subLoan);
if (!res)
return res;

Expand Down
5 changes: 2 additions & 3 deletions src/masternodes/rpc_icxorderbook.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -283,11 +283,10 @@ UniValue icxcreateorder(const JSONRPCRequest& request) {
{
LOCK(cs_main);
DCT_ID idToken;
std::unique_ptr<CToken> token;

if (order.orderType == CICXOrder::TYPE_INTERNAL)
{
token = pcustomcsview->GetTokenGuessId(tokenFromSymbol, idToken);
auto token = pcustomcsview->GetTokenGuessId(tokenFromSymbol, idToken);
if (!token)
throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Token %s does not exist!", tokenFromSymbol));
order.idToken = idToken;
Expand All @@ -303,7 +302,7 @@ UniValue icxcreateorder(const JSONRPCRequest& request) {
}
else
{
token = pcustomcsview->GetTokenGuessId(tokenToSymbol, idToken);
auto token = pcustomcsview->GetTokenGuessId(tokenToSymbol, idToken);
if (!token)
throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Token %s does not exist!", tokenToSymbol));
order.idToken = idToken;
Expand Down
5 changes: 2 additions & 3 deletions src/masternodes/rpc_loan.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ UniValue setLoanTokenToJSON(CLoanSetLoanTokenImplementation const& loanToken, DC
if (!token)
return (UniValue::VNULL);

loanTokenObj.pushKV("token", tokenToJSON(tokenId, *static_cast<CTokenImplementation*>(token.get()), true));
loanTokenObj.pushKV("token", tokenToJSON(tokenId, *token, true));
loanTokenObj.pushKV("fixedIntervalPriceId", loanToken.fixedIntervalPriceId.first + "/" + loanToken.fixedIntervalPriceId.second);
loanTokenObj.pushKV("interest", ValueFromAmount(loanToken.interest));

Expand Down Expand Up @@ -131,9 +131,8 @@ UniValue setcollateraltoken(const JSONRPCRequest& request) {
LOCK(cs_main);

DCT_ID idToken;
std::unique_ptr<CToken> token;

token = pcustomcsview->GetTokenGuessId(tokenSymbol, idToken);
auto token = pcustomcsview->GetTokenGuessId(tokenSymbol, idToken);
if (!token)
throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Token %s does not exist!", tokenSymbol));
collToken.idToken = idToken;
Expand Down
2 changes: 1 addition & 1 deletion src/masternodes/rpc_tokens.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -444,7 +444,7 @@ UniValue gettoken(const JSONRPCRequest& request) {
DCT_ID id;
auto token = pcustomcsview->GetTokenGuessId(request.params[0].getValStr(), id);
if (token) {
return tokenToJSON(id, *static_cast<CTokenImplementation*>(token.get()), true);
return tokenToJSON(id, *token, true);
}
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Token not found");
}
Expand Down
48 changes: 21 additions & 27 deletions src/masternodes/tokens.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,16 +26,12 @@ std::string trim_ws(std::string const & str)
return str.substr(first, (last - first + 1));
}

std::unique_ptr<CToken> CTokensView::GetToken(DCT_ID id) const
boost::optional<CTokensView::CTokenImpl> CTokensView::GetToken(DCT_ID id) const
{
if (auto tokenImpl = ReadBy<ID, CTokenImpl>(id)) {
return MakeUnique<CTokenImpl>(*tokenImpl);
}

return {};
return ReadBy<ID, CTokenImpl>(id);
}

boost::optional<std::pair<DCT_ID, std::unique_ptr<CToken> > > CTokensView::GetToken(const std::string & symbolKey) const
boost::optional<std::pair<DCT_ID, boost::optional<CTokensView::CTokenImpl>>> CTokensView::GetToken(const std::string & symbolKey) const
{
DCT_ID id;
if (ReadBy<Symbol, std::string>(symbolKey, id)) {
Expand All @@ -55,7 +51,7 @@ boost::optional<std::pair<DCT_ID, CTokensView::CTokenImpl> > CTokensView::GetTok
return {};
}

std::unique_ptr<CToken> CTokensView::GetTokenGuessId(const std::string & str, DCT_ID & id) const
boost::optional<CTokensView::CTokenImpl> CTokensView::GetTokenGuessId(const std::string & str, DCT_ID & id) const
{
std::string const key = trim_ws(str);

Expand All @@ -71,13 +67,13 @@ std::unique_ptr<CToken> CTokensView::GetTokenGuessId(const std::string & str, DC
auto pair = GetTokenByCreationTx(tx);
if (pair) {
id = pair->first;
return MakeUnique<CTokenImpl>(pair->second);
return pair->second;
}
} else {
auto pair = GetToken(key);
if (pair) {
id = pair->first;
return std::move(pair->second);
return pair->second;
}
}
return {};
Expand Down Expand Up @@ -245,39 +241,37 @@ Res CTokensView::BayfrontFlagsCleanup()
return Res::Ok();
}

Res CTokensView::AddMintedTokens(const uint256 &tokenTx, CAmount const & amount)
Res CTokensView::AddMintedTokens(DCT_ID const &id, CAmount const & amount)
{
auto pair = GetTokenByCreationTx(tokenTx);
if (!pair) {
return Res::Err("token with creationTx %s does not exist!", tokenTx.ToString());
auto tokenImpl = GetToken(id);
if (!tokenImpl) {
return Res::Err("token with id %d does not exist!", id.v);
}
CTokenImpl & tokenImpl = pair->second;

auto resMinted = SafeAdd(tokenImpl.minted, amount);
if (!resMinted.ok) {
auto resMinted = SafeAdd(tokenImpl->minted, amount);
if (!resMinted) {
return Res::Err("overflow when adding to minted");
}
tokenImpl.minted = *resMinted.val;
tokenImpl->minted = resMinted;

WriteBy<ID>(pair->first, tokenImpl);
WriteBy<ID>(id, *tokenImpl);
return Res::Ok();
}

Res CTokensView::SubMintedTokens(const uint256 &tokenTx, CAmount const & amount)
Res CTokensView::SubMintedTokens(DCT_ID const &id, CAmount const & amount)
{
auto pair = GetTokenByCreationTx(tokenTx);
if (!pair) {
return Res::Err("token with creationTx %s does not exist!", tokenTx.ToString());
auto tokenImpl = GetToken(id);
if (!tokenImpl) {
return Res::Err("token with id %d does not exist!", id.v);
}
CTokenImpl & tokenImpl = pair->second;

auto resMinted = tokenImpl.minted - amount;
auto resMinted = tokenImpl->minted - amount;
if (resMinted < 0) {
return Res::Err("not enough tokens exist to subtract this amount");
}
tokenImpl.minted = resMinted;
tokenImpl->minted = resMinted;

WriteBy<ID>(pair->first, tokenImpl);
WriteBy<ID>(id, *tokenImpl);
return Res::Ok();
}

Expand Down
10 changes: 5 additions & 5 deletions src/masternodes/tokens.h
Original file line number Diff line number Diff line change
Expand Up @@ -142,11 +142,11 @@ class CTokensView : public virtual CStorageView
static const unsigned char DB_TOKEN_LASTID; // = 'L';

using CTokenImpl = CTokenImplementation;
std::unique_ptr<CToken> GetToken(DCT_ID id) const;
boost::optional<std::pair<DCT_ID, std::unique_ptr<CToken>>> GetToken(std::string const & symbol) const;
boost::optional<CTokenImpl> GetToken(DCT_ID id) const;
boost::optional<std::pair<DCT_ID, boost::optional<CTokensView::CTokenImpl>>> GetToken(std::string const & symbol) const;
// the only possible type of token (with creationTx) is CTokenImpl
boost::optional<std::pair<DCT_ID, CTokenImpl>> GetTokenByCreationTx(uint256 const & txid) const;
std::unique_ptr<CToken> GetTokenGuessId(const std::string & str, DCT_ID & id) const;
boost::optional<CTokensView::CTokenImpl> GetTokenGuessId(const std::string & str, DCT_ID & id) const;

void ForEachToken(std::function<bool(DCT_ID const &, CLazySerialize<CTokenImpl>)> callback, DCT_ID const & start = DCT_ID{0});

Expand All @@ -156,8 +156,8 @@ class CTokensView : public virtual CStorageView
Res UpdateToken(uint256 const & tokenTx, CToken const & newToken, bool isPreBayfront);

Res BayfrontFlagsCleanup();
Res AddMintedTokens(uint256 const & tokenTx, CAmount const & amount);
Res SubMintedTokens(uint256 const & tokenTx, CAmount const & amount);
Res AddMintedTokens(DCT_ID const & id, CAmount const & amount);
Res SubMintedTokens(DCT_ID const & id, CAmount const & amount);

// tags
struct ID { static constexpr uint8_t prefix() { return 'T'; } };
Expand Down
2 changes: 1 addition & 1 deletion src/rpc/rawtransaction_util.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ ResVal<CTokenAmount> GuessTokenAmount(interfaces::Chain const & chain, std::stri
return {{tokenId, parsed.val->first}, Res::Ok()};
} catch (...) {
// assuming it's token symbol, read DCT_ID from DB
std::unique_ptr<CToken> token = chain.existTokenGuessId(parsed.val->second, tokenId);
auto token = chain.existTokenGuessId(parsed.val->second, tokenId);
if (!token) {
return Res::Err("Invalid Defi token: %s", parsed.val->second);
}
Expand Down
Loading

0 comments on commit 35ad71b

Please sign in to comment.