Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Track DUSD minted components #1487

Merged
merged 15 commits into from
Nov 11, 2022
Merged
16 changes: 16 additions & 0 deletions src/masternodes/govvariables/attributes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ const std::map<uint8_t, std::string>& ATTRIBUTES::displayParamsIDs() {
{ParamIDs::TokenID, "token"},
{ParamIDs::Economy, "economy"},
{ParamIDs::Feature, "feature"},
{ParamIDs::Auction, "auction"},
{ParamIDs::Foundation, "foundation"},
};
return params;
Expand Down Expand Up @@ -225,6 +226,7 @@ const std::map<uint8_t, std::map<uint8_t, std::string>>& ATTRIBUTES::displayKeys
{
AttributeTypes::Live, {
{EconomyKeys::PaybackDFITokens, "dfi_payback_tokens"},
{EconomyKeys::PaybackDFITokensPrincipal,"dfi_payback_tokens_principal"},
{EconomyKeys::DFIP2203Current, "dfip2203_current"},
{EconomyKeys::DFIP2203Burned, "dfip2203_burned"},
{EconomyKeys::DFIP2203Minted, "dfip2203_minted"},
Expand All @@ -234,6 +236,8 @@ const std::map<uint8_t, std::map<uint8_t, std::string>>& ATTRIBUTES::displayKeys
{EconomyKeys::DFIP2206FMinted, "dfip2206f_minted"},
{EconomyKeys::NegativeInt, "negative_interest"},
{EconomyKeys::NegativeIntCurrent, "negative_interest_current"},
{EconomyKeys::BatchRoundingExcess, "batch_rounding_excess"},
{EconomyKeys::ConsolidatedInterest, "consolidated_interest"},
{EconomyKeys::Loans, "loans"},
}
},
Expand Down Expand Up @@ -508,6 +512,18 @@ void TrackDUSDSub(CCustomCSView& mnview, const CTokenAmount& amount) {
TrackLiveBalance(mnview, amount, EconomyKeys::Loans, false);
}

void TrackLiveBalances(CCustomCSView& mnview, const CBalances& balances, const uint8_t key) {
auto attributes = mnview.GetAttributes();
assert(attributes);
const CDataStructureV0 liveKey{AttributeTypes::Live, ParamIDs::Auction, key};
auto storedBalances = attributes->GetValue(liveKey, CBalances{});
for (const auto& [tokenID, amount] : balances.balances) {
storedBalances.balances[tokenID] += amount;
}
attributes->SetValue(liveKey, storedBalances);
mnview.SetVariable(*attributes);
}

Res ATTRIBUTES::ProcessVariable(const std::string& key, std::optional<std::string> value,
std::function<Res(const CAttributeType&, const CAttributeValue&)> applyVariable) {

Expand Down
9 changes: 7 additions & 2 deletions src/masternodes/govvariables/attributes.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ enum ParamIDs : uint8_t {
DFIP2206A = 'f',
DFIP2206F = 'g',
Feature = 'h',
Foundation = 'i',
Auction = 'i',
Foundation = 'j',
};

enum OracleIDs : uint8_t {
Expand All @@ -50,7 +51,10 @@ enum EconomyKeys : uint8_t {
DexTokens = 'i',
NegativeInt = 'j',
NegativeIntCurrent = 'k',
Loans = 'l',
BatchRoundingExcess = 'l', // Extra added to loan amounts on auction creation due to round errors.
ConsolidatedInterest = 'm', // Amount added to loan amounts after auction with no bids.
PaybackDFITokensPrincipal = 'n', // Same as PaybackDFITokens but without interest.
Loans = 'o',
};

enum DFIPKeys : uint8_t {
Expand Down Expand Up @@ -205,6 +209,7 @@ using CAttributeType = std::variant<CDataStructureV0, CDataStructureV1>;
using CAttributeValue = std::variant<bool, CAmount, CBalances, CTokenPayback, CTokenCurrencyPair, OracleSplits, DescendantValue, AscendantValue, CFeeDir, CDexBalances, std::set<CScript>, std::set<std::string>>;

void TrackNegativeInterest(CCustomCSView& mnview, const CTokenAmount& amount);
void TrackLiveBalances(CCustomCSView& mnview, const CBalances& balances, const uint8_t key);
void TrackDUSDAdd(CCustomCSView& mnview, const CTokenAmount& amount);
void TrackDUSDSub(CCustomCSView& mnview, const CTokenAmount& amount);

Expand Down
16 changes: 10 additions & 6 deletions src/masternodes/mn_checks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3788,14 +3788,14 @@ class CCustomTxApplyVisitor : public CCustomTxVisitor

if (paybackTokenId == loanTokenId)
{
res = mnview.SubMintedTokens(loanTokenId, subInterest > 0 ? subLoan : subLoan + subInterest);
if (!res)
return res;

// If interest was negative remove it from sub amount
if (height >= static_cast<uint32_t>(consensus.FortCanningEpilogueHeight) && subInterest < 0)
subLoan += subInterest;

res = mnview.SubMintedTokens(loanTokenId, subLoan);
if (!res)
return res;

// Do not sub balance if negative interest fully negates the current loan amount
if (!(subInterest < 0 && std::abs(subInterest) >= currentLoanAmount)) {

Expand Down Expand Up @@ -3854,9 +3854,13 @@ class CCustomTxApplyVisitor : public CCustomTxVisitor
{
CDataStructureV0 liveKey{AttributeTypes::Live, ParamIDs::Economy, EconomyKeys::PaybackDFITokens};
auto balances = attributes->GetValue(liveKey, CBalances{});
balances.Add({loanTokenId, subAmount});
balances.Add({paybackTokenId, penalty});
attributes->SetValue(liveKey, balances);

balances.Add(CTokenAmount{loanTokenId, subAmount});
balances.Add(CTokenAmount{paybackTokenId, penalty});
liveKey.key = EconomyKeys::PaybackDFITokensPrincipal;
balances = attributes->GetValue(liveKey, CBalances{});
balances.Add({loanTokenId, subLoan});
attributes->SetValue(liveKey, balances);

LogPrint(BCLog::LOAN, "CLoanPaybackLoanMessage(): Burning interest and loan in %s directly - total loan %lld (%lld %s), height - %d\n", paybackToken->symbol, subLoan + subInterest, subInToken, paybackToken->symbol, height);
Expand Down
44 changes: 44 additions & 0 deletions src/validation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3410,18 +3410,37 @@ void CChainState::ProcessLoanEvents(const CBlockIndex* pindex, CCustomCSView& ca
auto batches = CollectAuctionBatches(*collateral.val, collaterals.balances, loanTokens->balances);

// Now, let's add the remaining amounts and store the batch.
CBalances totalLoanInBatches{};
for (auto i = 0u; i < batches.size(); i++) {
auto& batch = batches[i];
totalLoanInBatches.Add(batch.loanAmount);
auto tokenId = batch.loanAmount.nTokenId;
auto interest = totalInterest.balances[tokenId];
if (interest > 0) {
auto balance = loanTokens->balances[tokenId];
auto interestPart = DivideAmounts(batch.loanAmount.nValue, balance);
batch.loanInterest = MultiplyAmounts(interestPart, interest);
totalLoanInBatches.Sub({tokenId, batch.loanInterest});
}
cache.StoreAuctionBatch({vaultId, i}, batch);
}

// Check if more than loan amount was generated.
CBalances balances;
for (const auto& [tokenId, amount] : loanTokens->balances) {
if (totalLoanInBatches.balances.count(tokenId)) {
const auto interest = totalInterest.balances.count(tokenId) ? totalInterest.balances[tokenId] : 0;
if (totalLoanInBatches.balances[tokenId] > amount - interest) {
balances.Add({tokenId, totalLoanInBatches.balances[tokenId] - (amount - interest)});
}
}
}

// Only store to attributes if there has been a rounding error.
if (!balances.balances.empty()) {
TrackLiveBalances(cache, balances, EconomyKeys::BatchRoundingExcess);
}

// All done. Ready to save the overall auction.
cache.StoreAuction(vaultId, CAuctionData{
uint32_t(batches.size()),
Expand All @@ -3448,6 +3467,7 @@ void CChainState::ProcessLoanEvents(const CBlockIndex* pindex, CCustomCSView& ca
auto vault = view.GetVault(vaultId);
assert(vault);

CBalances balances;
for (uint32_t i = 0; i < data.batchCount; i++) {
auto batch = view.GetAuctionBatch({vaultId, i});
assert(batch);
Expand Down Expand Up @@ -3505,6 +3525,7 @@ void CChainState::ProcessLoanEvents(const CBlockIndex* pindex, CCustomCSView& ca
} else {
// we should return loan including interest
view.AddLoanToken(vaultId, batch->loanAmount);
balances.Add({batch->loanAmount.nTokenId, batch->loanInterest});

// When tracking loan amounts remove interest.
if (const auto token = view.GetToken("DUSD"); token && token->first == batch->loanAmount.nTokenId) {
Expand All @@ -3522,6 +3543,11 @@ void CChainState::ProcessLoanEvents(const CBlockIndex* pindex, CCustomCSView& ca
}
}

// Only store to attributes if there has been a rounding error.
if (!balances.balances.empty()) {
TrackLiveBalances(view, balances, EconomyKeys::ConsolidatedInterest);
}

vault->isUnderLiquidation = false;
view.StoreVault(vaultId, *vault);
view.EraseAuction(vaultId, pindex->nHeight);
Expand Down Expand Up @@ -4754,6 +4780,21 @@ static Res VaultSplits(CCustomCSView& view, ATTRIBUTES& attributes, const DCT_ID
return Res::Ok();
}

static void MigrateV1Remnants(const CCustomCSView &cache, ATTRIBUTES &attributes, const uint8_t key, const DCT_ID oldId, const DCT_ID newId, const int32_t multiplier, const uint8_t typeID = ParamIDs::Economy) {
CDataStructureV0 attrKey{AttributeTypes::Live, typeID, key};
auto balances = attributes.GetValue(attrKey, CBalances{});
for (auto it = balances.balances.begin(); it != balances.balances.end(); ++it) {
const auto& [tokenId, amount] = *it;
if (tokenId != oldId) {
continue;
}
balances.balances.erase(it);
balances.Add({newId, CalculateNewAmount(multiplier, amount)});
break;
}
attributes.SetValue(attrKey, balances);
}

void CChainState::ProcessTokenSplits(const CBlock& block, const CBlockIndex* pindex, CCustomCSView& cache, const CreationTxs& creationTxs, const CChainParams& chainparams) {
if (pindex->nHeight < chainparams.GetConsensus().FortCanningCrunchHeight) {
return;
Expand Down Expand Up @@ -4868,6 +4909,9 @@ void CChainState::ProcessTokenSplits(const CBlock& block, const CBlockIndex* pin
CDataStructureV0 descendantKey{AttributeTypes::Token, oldTokenId.v, TokenKeys::Descendant};
attributes->SetValue(descendantKey, DescendantValue{newTokenId.v, static_cast<int32_t>(pindex->nHeight)});

MigrateV1Remnants(cache, *attributes, EconomyKeys::BatchRoundingExcess, oldTokenId, newTokenId, multiplier, ParamIDs::Auction);
MigrateV1Remnants(cache, *attributes, EconomyKeys::ConsolidatedInterest, oldTokenId, newTokenId, multiplier, ParamIDs::Auction);

CAmount totalBalance{0};

res = PoolSplits(view, totalBalance, *attributes, oldTokenId, newTokenId, pindex, creationTxs, multiplier);
Expand Down
11 changes: 2 additions & 9 deletions test/functional/feature_loan_vault.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ def set_test_params(self):
self.owner_addresses = []
self.oracles = []

def move_to_gw_fork(self):
def move_to_fork(self):
result = self.nodes[0].listcollateraltokens()
assert_equal(result[0]['token'], 'DFI')
assert_equal(result[0]['factor'], Decimal('1.00000000'))
Expand Down Expand Up @@ -736,14 +736,7 @@ def overflowed_collateral_value(self):

def loan_and_collateral_token_to_govvar(self):
# Move to hard fork
self.move_to_gw_fork()

# Invalidate fork block
self.nodes[0].invalidateblock(self.nodes[0].getblockhash(self.nodes[0].getblockcount()))
assert_equal(len(self.nodes[0].getgov('ATTRIBUTES')['ATTRIBUTES']), 0)

# Move to hard fork again
self.move_to_gw_fork()
self.move_to_fork()

# Test setting collateral token partially
self.nodes[0].setgov({"ATTRIBUTES":{f'v0/token/{self.idETH}/fixed_interval_price_id':'ETH/USD', f'v0/token/{self.idETH}/loan_collateral_enabled':'true'}})
Expand Down