From ed5daaa98d8df41b646335e7be51bd58af596c5a Mon Sep 17 00:00:00 2001 From: Anthony Fieroni Date: Mon, 31 Jan 2022 08:29:23 +0200 Subject: [PATCH] Fix interest per block float calculation Signed-off-by: Anthony Fieroni --- src/masternodes/loan.cpp | 31 ++++++++++++++++--------------- src/test/amount_tests.cpp | 7 +++++++ 2 files changed, 23 insertions(+), 15 deletions(-) diff --git a/src/masternodes/loan.cpp b/src/masternodes/loan.cpp index a4f2b9e7f27..7f48338ee89 100644 --- a/src/masternodes/loan.cpp +++ b/src/masternodes/loan.cpp @@ -222,17 +222,6 @@ inline base_uint<128> InterestPerBlockCalculationV2(CAmount amount, CAmount toke return arith_uint256(amount) * netInterest * COIN / blocksPerYear; } -static base_uint<128> InterestPerBlockCalculation(CAmount amount, CAmount tokenInterest, CAmount schemeInterest, uint32_t height) -{ - if (int(height) >= Params().GetConsensus().FortCanningHillHeight) - return InterestPerBlockCalculationV2(amount, tokenInterest, schemeInterest); - - if (int(height) >= Params().GetConsensus().FortCanningMuseumHeight) - return std::ceil(InterestPerBlockCalculationV1(amount, tokenInterest, schemeInterest)); - - return InterestPerBlockCalculationV1(amount, tokenInterest, schemeInterest); -} - CAmount CeilInterest(const base_uint<128>& value, uint32_t height) { if (int(height) >= Params().GetConsensus().FortCanningHillHeight) { @@ -303,9 +292,15 @@ Res CLoanView::StoreInterest(uint32_t height, const CVaultId& vaultId, const std if (int(height) >= Params().GetConsensus().FortCanningHillHeight) { CBalances amounts; ReadBy(vaultId, amounts); - rate.interestPerBlock = InterestPerBlockCalculation(amounts.balances[id], token->interest, scheme->rate, height); + rate.interestPerBlock = InterestPerBlockCalculationV2(amounts.balances[id], token->interest, scheme->rate); + + } else if (int(height) >= Params().GetConsensus().FortCanningMuseumHeight) { + CAmount interestPerBlock = rate.interestPerBlock.GetLow64(); + interestPerBlock += std::ceil(InterestPerBlockCalculationV1(loanIncreased, token->interest, scheme->rate)); + rate.interestPerBlock = interestPerBlock; + } else - rate.interestPerBlock += InterestPerBlockCalculation(loanIncreased, token->interest, scheme->rate, height); + rate.interestPerBlock += InterestPerBlockCalculationV1(loanIncreased, token->interest, scheme->rate); rate.height = height; @@ -345,9 +340,15 @@ Res CLoanView::EraseInterest(uint32_t height, const CVaultId& vaultId, const std if (int(height) >= Params().GetConsensus().FortCanningHillHeight) { CBalances amounts; ReadBy(vaultId, amounts); - rate.interestPerBlock = InterestPerBlockCalculation(amounts.balances[id], token->interest, scheme->rate, height); + rate.interestPerBlock = InterestPerBlockCalculationV2(amounts.balances[id], token->interest, scheme->rate); + + } else if (int(height) >= Params().GetConsensus().FortCanningMuseumHeight) { + CAmount interestPerBlock = rate.interestPerBlock.GetLow64(); + CAmount newInterestPerBlock = std::ceil(InterestPerBlockCalculationV1(loanDecreased, token->interest, scheme->rate)); + rate.interestPerBlock = std::max(CAmount{0}, interestPerBlock - newInterestPerBlock); + } else { - auto interestPerBlock = InterestPerBlockCalculation(loanDecreased, token->interest, scheme->rate, height); + auto interestPerBlock = InterestPerBlockCalculationV1(loanDecreased, token->interest, scheme->rate); rate.interestPerBlock = rate.interestPerBlock < interestPerBlock ? 0 : rate.interestPerBlock - interestPerBlock; } diff --git a/src/test/amount_tests.cpp b/src/test/amount_tests.cpp index 49bcc350ef5..250e9ddae8f 100644 --- a/src/test/amount_tests.cpp +++ b/src/test/amount_tests.cpp @@ -147,4 +147,11 @@ BOOST_AUTO_TEST_CASE(CTokenAmount_Sub_Negative_Result_Test) BOOST_CHECK_EQUAL(amount.Sub(val).msg, "amount 0.00000010 is less than 0.00000011"); } +BOOST_AUTO_TEST_CASE(CAmount_Float_Test) +{ + CAmount amount1 = 16765189, amount2 = 237824; + // https://en.wikipedia.org/wiki/Floating-point_arithmetic + BOOST_CHECK_EQUAL(CAmount(amount1 + float(amount2)), amount1 + amount2 - 1); +} + BOOST_AUTO_TEST_SUITE_END()