From 8e5f7741ebc943e6f930ab57799140c04e1174ac Mon Sep 17 00:00:00 2001 From: Anthony Fieroni Date: Tue, 6 Apr 2021 17:03:06 +0300 Subject: [PATCH] Fork out rewards redistribution per block Signed-off-by: Anthony Fieroni --- src/masternodes/poolpairs.cpp | 110 ++++++++++++++++++++++------------ src/masternodes/poolpairs.h | 2 +- src/validation.cpp | 21 +++++-- 3 files changed, 90 insertions(+), 43 deletions(-) diff --git a/src/masternodes/poolpairs.cpp b/src/masternodes/poolpairs.cpp index c8c1849938..382e776dfb 100644 --- a/src/masternodes/poolpairs.cpp +++ b/src/masternodes/poolpairs.cpp @@ -416,9 +416,10 @@ CAmount CPoolPair::slopeSwap(CAmount unswapped, CAmount &poolFrom, CAmount &pool return swapped.GetLow64(); } -CAmount CPoolPairView::UpdatePoolRewards(std::function onGetBalance, std::function onTransfer, int nHeight) { +CAmount CPoolPairView::UpdatePoolRewards(std::function onGetBalance, std::function onTransfer, int nHeight) { bool newRewardCalc = nHeight >= Params().GetConsensus().BayfrontGardensHeight; + bool newRewardLogic = nHeight >= Params().GetConsensus().EunosHeight; constexpr uint32_t const PRECISION = 10000; // (== 100%) just searching the way to avoid arith256 inflating CAmount totalDistributed = 0; @@ -428,11 +429,6 @@ CAmount CPoolPairView::UpdatePoolRewards(std::function(this, poolKey); - auto customRewards = ReadValueAt(this, poolKey); - auto rewards = pool.rewards; for (auto it = rewards.balances.begin(), next_it = it; it != rewards.balances.end(); it = next_it) { ++next_it; @@ -446,51 +442,89 @@ CAmount CPoolPairView::UpdatePoolRewards(std::function(this, poolKey); + if (rewards != customRewards) { WriteBy(poolKey, rewards); } - if (pool.totalLiquidity == 0 || (!pool.swapEvent && poolReward == 0 && rewards.balances.empty())) { - return true; // no events, skip to the next pool + if (!pool.totalLiquidity) { + return true; } - ForEachPoolShare([&] (DCT_ID const & currentId, CScript const & provider, uint32_t) { - if (currentId != poolId) { - return false; // stop - } - CAmount const liquidity = onGetBalance(provider, poolId).nValue; + auto poolReward = ReadValueAt(this, poolKey); - uint32_t const liqWeight = liquidity * PRECISION / pool.totalLiquidity; - assert (liqWeight < PRECISION); + if (newRewardLogic) { - // distribute trading fees if (pool.swapEvent) { - if (newRewardCalc) { - distributedFeeA += liquidityReward(pool.blockCommissionA, liquidity, pool.totalLiquidity); - distributedFeeB += liquidityReward(pool.blockCommissionB, liquidity, pool.totalLiquidity); - } else { - distributedFeeA += pool.blockCommissionA * liqWeight / PRECISION; - distributedFeeB += pool.blockCommissionB * liqWeight / PRECISION; - } + // it clears block commission + distributedFeeA = pool.blockCommissionA; + distributedFeeB = pool.blockCommissionB; } - // distribute yield farming - if (poolReward) { - if (newRewardCalc) { - totalDistributed += liquidityReward(poolReward, liquidity, pool.totalLiquidity); - } else { - totalDistributed += poolReward * liqWeight / PRECISION; - } - } + // increase by pool block reward + totalDistributed += poolReward; for (const auto& reward : rewards.balances) { - if (auto providerReward = liquidityReward(reward.second, liquidity, pool.totalLiquidity)) { - onTransfer(pool.ownerAddress, {reward.first, providerReward}); - } + // subtract pool's owner account by custom block reward + onTransfer(pool.ownerAddress, {}, {reward.first, reward.second}); } - return true; - }, PoolShareKey{poolId, CScript{}}); + } else { + if (!pool.swapEvent && poolReward == 0 && rewards.balances.empty()) { + return true; // no events, skip to the next pool + } + + ForEachPoolShare([&] (DCT_ID const & currentId, CScript const & provider, uint32_t) { + if (currentId != poolId) { + return false; // stop + } + CAmount const liquidity = onGetBalance(provider, poolId).nValue; + + uint32_t const liqWeight = liquidity * PRECISION / pool.totalLiquidity; + assert (liqWeight < PRECISION); + + // distribute trading fees + if (pool.swapEvent) { + CAmount feeA, feeB; + if (newRewardCalc) { + feeA = liquidityReward(pool.blockCommissionA, liquidity, pool.totalLiquidity); + feeB = liquidityReward(pool.blockCommissionB, liquidity, pool.totalLiquidity); + } else { + feeA = pool.blockCommissionA * liqWeight / PRECISION; + feeB = pool.blockCommissionB * liqWeight / PRECISION; + } + if (onTransfer({}, provider, {pool.idTokenA, feeA})) { + distributedFeeA += feeA; + } + if (onTransfer({}, provider, {pool.idTokenB, feeB})) { + distributedFeeB += feeB; + } + } + + // distribute yield farming + if (poolReward) { + CAmount providerReward; + if (newRewardCalc) { + providerReward = liquidityReward(poolReward, liquidity, pool.totalLiquidity); + } else { + providerReward = poolReward * liqWeight / PRECISION; + } + if (onTransfer({}, provider, {DCT_ID{0}, providerReward})) { + totalDistributed += providerReward; + } + } + + for (const auto& reward : rewards.balances) { + if (auto providerReward = liquidityReward(reward.second, liquidity, pool.totalLiquidity)) { + onTransfer(pool.ownerAddress, provider, {reward.first, providerReward}); + } + } + + return true; + }, PoolShareKey{poolId, CScript{}}); + } if (pool.swapEvent) { pool.blockCommissionA -= distributedFeeA; @@ -523,7 +557,9 @@ boost::optional CPoolPairView::GetShare(DCT_ID const & poolId, CScript Res CPoolPairView::SetDailyReward(uint32_t height, CAmount reward) { ForEachPoolPair([&](DCT_ID const & id, CPoolPair pool) { - WriteBy(PoolHeightKey{id, height}, PoolRewardPerBlock(reward, pool.rewardPct)); + if (pool.rewardPct != 0) { + WriteBy(PoolHeightKey{id, height}, PoolRewardPerBlock(reward, pool.rewardPct)); + } return true; }); WriteBy(PoolHeightKey{{}, height}, reward); diff --git a/src/masternodes/poolpairs.h b/src/masternodes/poolpairs.h index 59b4d02e2a..d185bdb1e6 100644 --- a/src/masternodes/poolpairs.h +++ b/src/masternodes/poolpairs.h @@ -214,7 +214,7 @@ class CPoolPairView : public virtual CStorageView Res SetDailyReward(uint32_t height, CAmount reward); - CAmount UpdatePoolRewards(std::function onGetBalance, std::function onTransfer, int nHeight = 0); + CAmount UpdatePoolRewards(std::function onGetBalance, std::function onTransfer, int nHeight = 0); // tags struct ByID { static const unsigned char prefix; }; // lsTokenID -> СPoolPair diff --git a/src/validation.cpp b/src/validation.cpp index 046bd0ccde..3fd88d2d2c 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -2367,12 +2367,23 @@ bool CChainState::ConnectBlock(const CBlock& block, CValidationState& state, CBl cache.CalculateOwnerRewards(owner, pindex->nHeight); return cache.GetBalance(owner, tokenID); }, - [&](CScript const & owner, CTokenAmount amount) { - auto res = cache.SubBalance(owner, amount); - if (!res) { - LogPrintf("Custom pool rewards: can't subtract balance of %s: %s, height %ld\n", owner.GetHex(), res.msg, pindex->nHeight); + [&](CScript const & from, CScript const & to, CTokenAmount amount) { + if (!from.empty()) { + auto res = cache.SubBalance(from, amount); + if (!res) { + LogPrintf("Custom pool rewards: can't subtract balance of %s: %s, height %ld\n", from.GetHex(), res.msg, pindex->nHeight); + return res; + } + } + if (!to.empty()) { + auto res = cache.AddBalance(to, amount); + if (!res) { + LogPrintf("Can't apply reward to %s: %s, %ld\n", to.GetHex(), res.msg, pindex->nHeight); + return res; + } + cache.UpdateBalancesHeight(to, pindex->nHeight + 1); } - return res; + return Res::Ok(); }, pindex->nHeight );