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

Burn loan interest in DUSD instead of swapping to DFI #1357

Merged
merged 5 commits into from
Jun 23, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 39 additions & 24 deletions src/masternodes/govvariables/attributes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ const std::map<std::string, uint8_t>& ATTRIBUTES::allowedParamIDs() {
static const std::map<std::string, uint8_t> params{
{"dfip2201", ParamIDs::DFIP2201},
{"dfip2203", ParamIDs::DFIP2203},
{"dfip2206a", ParamIDs::DFIP2206A},
};
return params;
}
Expand All @@ -92,6 +93,7 @@ const std::map<uint8_t, std::string>& ATTRIBUTES::displayParamsIDs() {
static const std::map<uint8_t, std::string> params{
{ParamIDs::DFIP2201, "dfip2201"},
{ParamIDs::DFIP2203, "dfip2203"},
{ParamIDs::DFIP2206A, "dfip2206a"},
{ParamIDs::TokenID, "token"},
{ParamIDs::Economy, "economy"},
};
Expand Down Expand Up @@ -140,11 +142,13 @@ const std::map<uint8_t, std::map<std::string, uint8_t>>& ATTRIBUTES::allowedKeys
},
{
AttributeTypes::Param, {
{"active", DFIPKeys::Active},
{"minswap", DFIPKeys::MinSwap},
{"premium", DFIPKeys::Premium},
{"reward_pct", DFIPKeys::RewardPct},
{"block_period", DFIPKeys::BlockPeriod},
{"active", DFIPKeys::Active},
{"minswap", DFIPKeys::MinSwap},
{"premium", DFIPKeys::Premium},
{"reward_pct", DFIPKeys::RewardPct},
{"block_period", DFIPKeys::BlockPeriod},
{"direct_interest_dusd_burn", DFIPKeys::DirectInterestDUSDBurn},
{"direct_loan_dusd_burn", DFIPKeys::DirectLoanDUSDBurn},
}
},
};
Expand Down Expand Up @@ -182,11 +186,13 @@ const std::map<uint8_t, std::map<uint8_t, std::string>>& ATTRIBUTES::displayKeys
},
{
AttributeTypes::Param, {
{DFIPKeys::Active, "active"},
{DFIPKeys::Premium, "premium"},
{DFIPKeys::MinSwap, "minswap"},
{DFIPKeys::RewardPct, "reward_pct"},
{DFIPKeys::BlockPeriod, "block_period"},
{DFIPKeys::Active, "active"},
{DFIPKeys::Premium, "premium"},
{DFIPKeys::MinSwap, "minswap"},
{DFIPKeys::RewardPct, "reward_pct"},
{DFIPKeys::BlockPeriod, "block_period"},
{DFIPKeys::DirectInterestDUSDBurn, "direct_interest_dusd_burn"},
{DFIPKeys::DirectLoanDUSDBurn, "direct_loan_dusd_burn"},
}
},
{
Expand Down Expand Up @@ -338,11 +344,13 @@ const std::map<uint8_t, std::map<uint8_t,
},
{
AttributeTypes::Param, {
{DFIPKeys::Active, VerifyBool},
{DFIPKeys::Premium, VerifyPct},
{DFIPKeys::MinSwap, VerifyFloat},
{DFIPKeys::RewardPct, VerifyPct},
{DFIPKeys::BlockPeriod, VerifyInt64},
{DFIPKeys::Active, VerifyBool},
{DFIPKeys::Premium, VerifyPct},
{DFIPKeys::MinSwap, VerifyFloat},
{DFIPKeys::RewardPct, VerifyPct},
{DFIPKeys::BlockPeriod, VerifyInt64},
{DFIPKeys::DirectInterestDUSDBurn, VerifyBool},
{DFIPKeys::DirectLoanDUSDBurn, VerifyBool},
}
},
{
Expand Down Expand Up @@ -418,7 +426,7 @@ Res ATTRIBUTES::ProcessVariable(const std::string& key, const std::string& value
if (type == AttributeTypes::Param) {
auto id = allowedParamIDs().find(keys[2]);
if (id == allowedParamIDs().end()) {
return ::ShowError("params", allowedParamIDs());
return ::ShowError("param", allowedParamIDs());
}
typeId = id->second;
} else if (type == AttributeTypes::Locks) {
Expand Down Expand Up @@ -469,20 +477,25 @@ Res ATTRIBUTES::ProcessVariable(const std::string& key, const std::string& value

if (type == AttributeTypes::Param) {
if (typeId == ParamIDs::DFIP2201) {
if (typeKey == DFIPKeys::RewardPct ||
typeKey == DFIPKeys::BlockPeriod) {
if (typeKey != DFIPKeys::Active && typeKey != DFIPKeys::Premium &&
typeKey != DFIPKeys::MinSwap ) {
return Res::Err("Unsupported type for DFIP2201 {%d}", typeKey);
}
} else if (typeId == ParamIDs::DFIP2203) {
if (typeKey == DFIPKeys::Premium ||
typeKey == DFIPKeys::MinSwap) {
if (typeKey != DFIPKeys::Active && typeKey != DFIPKeys::RewardPct &&
typeKey != DFIPKeys::BlockPeriod) {
return Res::Err("Unsupported type for DFIP2203 {%d}", typeKey);
}

if (typeKey == DFIPKeys::BlockPeriod) {
futureBlockUpdated = true;
}
} else {
} else if (typeId == ParamIDs::DFIP2206A) {
if (typeKey != DFIPKeys::DirectInterestDUSDBurn &&
typeKey != DFIPKeys::DirectLoanDUSDBurn) {
return Res::Err("Unsupported type for DFIP2206A {%d}", typeKey);
}
} else {
return Res::Err("Unsupported Param ID");
}
}
Expand Down Expand Up @@ -889,10 +902,12 @@ Res ATTRIBUTES::Validate(const CCustomCSView & view) const
break;

case AttributeTypes::Param:
if (attrV0->typeId == ParamIDs::DFIP2203) {
if (view.GetLastHeight() < Params().GetConsensus().FortCanningRoadHeight) {
if (attrV0->typeId == ParamIDs::DFIP2206A) {
if (view.GetLastHeight() < Params().GetConsensus().FortCanningGardensHeight)
return Res::Err("Cannot be set before FortCanningGarden");
} else if (attrV0->typeId == ParamIDs::DFIP2203) {
if (view.GetLastHeight() < Params().GetConsensus().FortCanningRoadHeight)
return Res::Err("Cannot be set before FortCanningRoad");
}
} else if (attrV0->typeId != ParamIDs::DFIP2201) {
return Res::Err("Unrecognised param id");
}
Expand Down
15 changes: 9 additions & 6 deletions src/masternodes/govvariables/attributes.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ enum ParamIDs : uint8_t {
DFIP2203 = 'b',
TokenID = 'c',
Economy = 'e',
DFIP2206A = 'f',
};

enum OracleIDs : uint8_t {
Expand All @@ -43,11 +44,13 @@ enum EconomyKeys : uint8_t {
};

enum DFIPKeys : uint8_t {
Active = 'a',
Premium = 'b',
MinSwap = 'c',
RewardPct = 'd',
BlockPeriod = 'e',
Active = 'a',
Premium = 'b',
MinSwap = 'c',
RewardPct = 'd',
BlockPeriod = 'e',
DirectInterestDUSDBurn = 'g',
DirectLoanDUSDBurn = 'h',
};

enum TokenKeys : uint8_t {
Expand Down Expand Up @@ -175,7 +178,7 @@ class ATTRIBUTES : public GovVariable, public AutoRegistrator<GovVariable, ATTRI
Res Import(UniValue const &val) override;
UniValue Export() const override;
UniValue ExportFiltered(GovVarsFilter filter, const std::string &prefix) const;

Res Validate(CCustomCSView const& mnview) const override;
Res Apply(CCustomCSView &mnview, const uint32_t height) override;

Expand Down
42 changes: 35 additions & 7 deletions src/masternodes/mn_checks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3316,7 +3316,7 @@ class CCustomTxApplyVisitor : public CCustomTxVisitor
if (subInterest)
{
LogPrint(BCLog::LOAN, "CLoanPaybackLoanMessage(): Swapping %s interest to DFI - %lld, height - %d\n", loanToken->symbol, subInterest, height);
res = SwapToDFIOverUSD(mnview, loanTokenId, subInterest, obj.from, consensus.burnAddress, height);
res = SwapToDFIorDUSD(mnview, loanTokenId, subInterest, obj.from, consensus.burnAddress, height);
}
}
else
Expand Down Expand Up @@ -3375,7 +3375,10 @@ class CCustomTxApplyVisitor : public CCustomTxVisitor

LogPrint(BCLog::LOAN, "CLoanPaybackLoanMessage(): Swapping %s to DFI and burning it - total loan %lld (%lld %s), height - %d\n", paybackToken->symbol, subLoan + subInterest, subInToken, paybackToken->symbol, height);

res = SwapToDFIOverUSD(mnview, paybackTokenId, subInToken, obj.from, consensus.burnAddress, height);
CDataStructureV0 directBurnKey{AttributeTypes::Param, ParamIDs::DFIP2206A, DFIPKeys::DirectLoanDUSDBurn};
auto directLoanBurn = attributes->GetValue(directBurnKey, false);

res = SwapToDFIorDUSD(mnview, paybackTokenId, subInToken, obj.from, consensus.burnAddress, height, !directLoanBurn);
}
}

Expand Down Expand Up @@ -4078,7 +4081,7 @@ Res CPoolSwap::ExecuteSwap(CCustomCSView& view, std::vector<DCT_ID> poolIDs, boo
return poolResult;
}

Res SwapToDFIOverUSD(CCustomCSView & mnview, DCT_ID tokenId, CAmount amount, CScript const & from, CScript const & to, uint32_t height)
Res SwapToDFIorDUSD(CCustomCSView & mnview, DCT_ID tokenId, CAmount amount, CScript const & from, CScript const & to, uint32_t height, bool forceLoanSwap)
{
CPoolSwapMessage obj;

Expand All @@ -4099,9 +4102,28 @@ Res SwapToDFIOverUSD(CCustomCSView & mnview, DCT_ID tokenId, CAmount amount, CS
if (!dUsdToken)
return Res::Err("Cannot find token DUSD");

const auto attributes = mnview.GetAttributes();
if (!attributes) {
return Res::Err("Attributes unavailable");
}
CDataStructureV0 directBurnKey{AttributeTypes::Param, ParamIDs::DFIP2206A, DFIPKeys::DirectInterestDUSDBurn};

// Direct swap from DUSD to DFI as defined in the CPoolSwapMessage.
if (tokenId == dUsdToken->first) {
return poolSwap.ExecuteSwap(mnview, {});
if (to == Params().GetConsensus().burnAddress && !forceLoanSwap && attributes->GetValue(directBurnKey, false))
{
// direct burn dUSD
CTokenAmount dUSD{dUsdToken->first, amount};

auto res = mnview.SubBalance(from, dUSD);
if (!res)
return res;

return mnview.AddBalance(to, dUSD);
}
else
// swap dUSD -> DFI and burn DFI
return poolSwap.ExecuteSwap(mnview, {});
}

auto pooldUSDDFI = mnview.GetPoolPair(dUsdToken->first, DCT_ID{0});
Expand All @@ -4112,10 +4134,16 @@ Res SwapToDFIOverUSD(CCustomCSView & mnview, DCT_ID tokenId, CAmount amount, CS
if (!poolTokendUSD)
return Res::Err("Cannot find pool pair %s-DUSD!", token->symbol);

// swap tokenID -> USD -> DFI
auto res = poolSwap.ExecuteSwap(mnview, {poolTokendUSD->first, pooldUSDDFI->first});
if (to == Params().GetConsensus().burnAddress && !forceLoanSwap && attributes->GetValue(directBurnKey, false))
{
obj.idTokenTo = dUsdToken->first;

return res;
// swap tokenID -> dUSD and burn dUSD
return poolSwap.ExecuteSwap(mnview, {});
}
else
// swap tokenID -> dUSD -> DFI and burn DFI
return poolSwap.ExecuteSwap(mnview, {poolTokendUSD->first, pooldUSDDFI->first});
}

bool IsVaultPriceValid(CCustomCSView& mnview, const CVaultId& vaultId, uint32_t height)
Expand Down
2 changes: 1 addition & 1 deletion src/masternodes/mn_checks.h
Original file line number Diff line number Diff line change
Expand Up @@ -393,7 +393,7 @@ ResVal<uint256> ApplyAnchorRewardTx(CCustomCSView& mnview, const CTransaction& t
ResVal<uint256> ApplyAnchorRewardTxPlus(CCustomCSView& mnview, const CTransaction& tx, int height, const std::vector<unsigned char>& metadata, const Consensus::Params& consensusParams);
ResVal<CAmount> GetAggregatePrice(CCustomCSView& view, const std::string& token, const std::string& currency, uint64_t lastBlockTime);
bool IsVaultPriceValid(CCustomCSView& mnview, const CVaultId& vaultId, uint32_t height);
Res SwapToDFIOverUSD(CCustomCSView & mnview, DCT_ID tokenId, CAmount amount, CScript const & from, CScript const & to, uint32_t height);
Res SwapToDFIorDUSD(CCustomCSView & mnview, DCT_ID tokenId, CAmount amount, CScript const & from, CScript const & to, uint32_t height, bool forceLoanSwap = false);
Res storeGovVars(const CGovernanceHeightMessage& obj, CCustomCSView& view);

inline bool OraclePriceFeed(CCustomCSView& view, const CTokenCurrencyPair& priceFeed) {
Expand Down
8 changes: 4 additions & 4 deletions src/masternodes/rpc_accounts.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1771,13 +1771,13 @@ UniValue getburninfo(const JSONRPCRequest& request) {
CAmount burntDFI{0};
CAmount burntFee{0};
CAmount auctionFee{0};
CAmount paybackFee{0};
CAmount dfiPaybackFee{0};
CAmount burnt{0};

CBalances burntTokens;
CBalances dexfeeburn;
CBalances paybackfees;
CBalances paybackFee;
CBalances paybacktokens;
CBalances dfi2203Tokens;
CBalances dfipaybacktokens;
Expand Down Expand Up @@ -1838,8 +1838,8 @@ UniValue getburninfo(const JSONRPCRequest& request) {
// withdraw burn
if (value.category == uint8_t(CustomTxType::PaybackLoan)
|| value.category == uint8_t(CustomTxType::PaybackLoanV2)) {
for (auto const & diff : value.diff) {
paybackFee += diff.second;
for (const auto& [id, amount] : value.diff) {
paybackFee.Add({id, amount});
}
return true;
}
Expand Down Expand Up @@ -1874,7 +1874,7 @@ UniValue getburninfo(const JSONRPCRequest& request) {
result.pushKV("tokens", AmountsToJSON(burntTokens.balances));
result.pushKV("feeburn", ValueFromAmount(burntFee));
result.pushKV("auctionburn", ValueFromAmount(auctionFee));
result.pushKV("paybackburn", ValueFromAmount(paybackFee));
result.pushKV("paybackburn", AmountsToJSON(paybackFee.balances));
result.pushKV("dexfeetokens", AmountsToJSON(dexfeeburn.balances));

result.pushKV("dfipaybackfee", ValueFromAmount(dfiPaybackFee));
Expand Down
22 changes: 11 additions & 11 deletions src/validation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2880,7 +2880,7 @@ bool CChainState::ConnectBlock(const CBlock& block, CValidationState& state, CBl
}
UpdateCoins(tx, view, i == 0 ? undoDummy : blockundo.vtxundo.back(), pindex->nHeight);
}

int64_t nTime3 = GetTimeMicros(); nTimeConnect += nTime3 - nTime2;
LogPrint(BCLog::BENCH, " - Connect %u transactions: %.2fms (%.3fms/tx, %.3fms/txin) [%.2fs (%.2fms/blk)]\n", (unsigned)block.vtx.size(), MILLI * (nTime3 - nTime2), MILLI * (nTime3 - nTime2) / block.vtx.size(), nInputs <= 1 ? 0 : MILLI * (nTime3 - nTime2) / (nInputs-1), nTimeConnect * MICRO, nTimeConnect * MILLI / nBlocksTotal);

Expand Down Expand Up @@ -3400,7 +3400,7 @@ void CChainState::ProcessLoanEvents(const CBlockIndex* pindex, CCustomCSView& ca

auto penaltyAmount = MultiplyAmounts(batch->loanAmount.nValue, COIN + data.liquidationPenalty);
if (bidTokenAmount.nValue < penaltyAmount) {
LogPrintf("WARNING: bidTokenAmount.nValue(%d) < penaltyAmount(%d)\n",
LogPrintf("WARNING: bidTokenAmount.nValue(%d) < penaltyAmount(%d)\n",
bidTokenAmount.nValue, penaltyAmount);
}
// penaltyAmount includes interest, batch as well, so we should put interest back
Expand All @@ -3409,7 +3409,7 @@ void CChainState::ProcessLoanEvents(const CBlockIndex* pindex, CCustomCSView& ca
if (amountToBurn > 0) {
CScript tmpAddress(vaultId.begin(), vaultId.end());
view.AddBalance(tmpAddress, {bidTokenAmount.nTokenId, amountToBurn});
SwapToDFIOverUSD(view, bidTokenAmount.nTokenId, amountToBurn, tmpAddress,
SwapToDFIorDUSD(view, bidTokenAmount.nTokenId, amountToBurn, tmpAddress,
chainparams.GetConsensus().burnAddress, pindex->nHeight);
}

Expand All @@ -3427,7 +3427,7 @@ void CChainState::ProcessLoanEvents(const CBlockIndex* pindex, CCustomCSView& ca
CScript tmpAddress(vaultId.begin(), vaultId.end());
view.AddBalance(tmpAddress, {bidTokenAmount.nTokenId, amountToFill});

SwapToDFIOverUSD(view, bidTokenAmount.nTokenId, amountToFill, tmpAddress, tmpAddress, pindex->nHeight);
SwapToDFIorDUSD(view, bidTokenAmount.nTokenId, amountToFill, tmpAddress, tmpAddress, pindex->nHeight);
auto amount = view.GetBalance(tmpAddress, DCT_ID{0});
view.SubBalance(tmpAddress, amount);
view.AddVaultCollateral(vaultId, amount);
Expand Down Expand Up @@ -3882,11 +3882,11 @@ size_t RewardConsolidationWorkersCount() {
// Note: Be careful with lambda captures and default args. GCC 11.2.0, appears the if the captures are
// unused in the function directly, but inside the lambda, it completely disassociates them from the fn
// possibly when the lambda is lifted up and with default args, ends up inling the default arg
// completely. TODO: verify with smaller test case.
// completely. TODO: verify with smaller test case.
// But scenario: If `interruptOnShutdown` is set as default arg to false, it will never be set true
// on the below as it's inlined by gcc 11.2.0 on Ubuntu 22.04 incorrectly. Behavior is correct
// in lower versions of gcc or across clang.
void ConsolidateRewards(CCustomCSView &view, int height,
// in lower versions of gcc or across clang.
void ConsolidateRewards(CCustomCSView &view, int height,
const std::vector<std::pair<CScript, CAmount>> &items, bool interruptOnShutdown, int numWorkers) {
int nWorkers = numWorkers < 1 ? RewardConsolidationWorkersCount() : numWorkers;
auto rewardsTime = GetTimeMicros();
Expand Down Expand Up @@ -4028,7 +4028,7 @@ static Res PoolSplits(CCustomCSView& view, CAmount& totalBalance, ATTRIBUTES& at
balancesToMigrate.size(), totalAccounts, nWorkers);

// Largest first to make sure we are over MINIMUM_LIQUIDITY on first call to AddLiquidity
std::sort(balancesToMigrate.begin(), balancesToMigrate.end(),
std::sort(balancesToMigrate.begin(), balancesToMigrate.end(),
[](const std::pair<CScript, CAmount>&a, const std::pair<CScript, CAmount>& b){
return a.second > b.second;
});
Expand Down Expand Up @@ -4265,9 +4265,9 @@ static Res VaultSplits(CCustomCSView& view, ATTRIBUTES& attributes, const DCT_ID
auto oldTokenAmount = CTokenAmount{oldTokenId, amount};
auto newTokenAmount = CTokenAmount{newTokenId, newAmount};

LogPrint(BCLog::TOKENSPLIT, "TokenSplit: V Loan (%s: %s => %s)\n",
LogPrint(BCLog::TOKENSPLIT, "TokenSplit: V Loan (%s: %s => %s)\n",
vaultId.ToString(), oldTokenAmount.ToString(), newTokenAmount.ToString());

res = view.AddLoanToken(vaultId, newTokenAmount);
if (!res) {
return res;
Expand Down Expand Up @@ -4356,7 +4356,7 @@ static Res VaultSplits(CCustomCSView& view, ATTRIBUTES& attributes, const DCT_ID
value.loanInterest = newLoanInterest;

LogPrint(BCLog::TOKENSPLIT, "TokenSplit: V AuctionL (%s,%d: %s => %s, %d => %d)\n",
key.first.ToString(), key.second, oldLoanAmount.ToString(),
key.first.ToString(), key.second, oldLoanAmount.ToString(),
newLoanAmount.ToString(), oldInterest, newLoanInterest);
}

Expand Down
Loading