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
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
@@ -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;
}
@@ -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"},
};
@@ -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},
}
},
};
@@ -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"},
}
},
{
@@ -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},
}
},
{
@@ -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) {
@@ -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");
}
}
@@ -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");
}
15 changes: 9 additions & 6 deletions src/masternodes/govvariables/attributes.h
Original file line number Diff line number Diff line change
@@ -28,6 +28,7 @@ enum ParamIDs : uint8_t {
DFIP2203 = 'b',
TokenID = 'c',
Economy = 'e',
DFIP2206A = 'f',
};

enum OracleIDs : uint8_t {
@@ -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 {
@@ -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;

42 changes: 35 additions & 7 deletions src/masternodes/mn_checks.cpp
Original file line number Diff line number Diff line change
@@ -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
@@ -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);
}
}

@@ -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;

@@ -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});
@@ -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)
2 changes: 1 addition & 1 deletion src/masternodes/mn_checks.h
Original file line number Diff line number Diff line change
@@ -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) {
8 changes: 4 additions & 4 deletions src/masternodes/rpc_accounts.cpp
Original file line number Diff line number Diff line change
@@ -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;
@@ -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;
}
@@ -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));
22 changes: 11 additions & 11 deletions src/validation.cpp
Original file line number Diff line number Diff line change
@@ -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);

@@ -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
@@ -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);
}

@@ -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);
@@ -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();
@@ -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;
});
@@ -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;
@@ -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);
}

Loading