Skip to content

Commit

Permalink
map refactored to array
Browse files Browse the repository at this point in the history
  • Loading branch information
ahmedrns committed Dec 21, 2022
1 parent 42bb0da commit 0547814
Show file tree
Hide file tree
Showing 5 changed files with 96 additions and 43 deletions.
62 changes: 42 additions & 20 deletions x/pylons/keeper/distribution.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ const (
BedRockHolderRewardPercentage = 90
)

func (k Keeper) GetRewardsDistributionPercentages(ctx sdk.Context, sk types.StakingKeeper) (distrPercentages map[string]sdk.Dec) {
distrPercentages = make(map[string]sdk.Dec)
func (k Keeper) GetRewardsDistributionPercentages(ctx sdk.Context, sk types.StakingKeeper) (distPercentages []types.DistributionPercentage) {
distrPercentages := make(map[string]sdk.Dec)
sharesMap := make(map[string]sdk.Dec)
validators := make(map[string]bool)
totalShares := sdk.ZeroDec()
Expand Down Expand Up @@ -74,7 +74,8 @@ func (k Keeper) GetRewardsDistributionPercentages(ctx sdk.Context, sk types.Stak
distrPercentages[valAccAddr.String()] = distrPercentages[valAccAddr.String()].Add(commissionPercentage)
}
}
return distrPercentages
distPercentage := convertMapToArray(distrPercentages)
return distPercentage
}

func (k Keeper) getTotalSupply(ctx sdk.Context, ak types.AccountKeeper, denom string) sdk.Dec {
Expand All @@ -97,7 +98,7 @@ func (k Keeper) getTotalSupply(ctx sdk.Context, ak types.AccountKeeper, denom st
return totalAvailable
}

func (k Keeper) GetHoldersRewardsDistributionPercentages(ctx sdk.Context, sk types.StakingKeeper, ak types.AccountKeeper) map[string]sdk.Dec {
func (k Keeper) GetHoldersRewardsDistributionPercentages(ctx sdk.Context, sk types.StakingKeeper, ak types.AccountKeeper) (distPercentages []types.DistributionPercentage) {
distrPercentages := make(map[string]sdk.Dec)
stakingDenom := types.StakingCoinDenom
// Get all account balances
Expand All @@ -118,7 +119,8 @@ func (k Keeper) GetHoldersRewardsDistributionPercentages(ctx sdk.Context, sk typ

}
}
return distrPercentages
distPercentage := convertMapToArray(distrPercentages)
return distPercentage
}

func calculateAvailableAmount(coin math.Int) sdk.Dec {
Expand All @@ -131,22 +133,26 @@ func calculateHolderAavailableAmount(coin math.Int) sdk.Dec {
return sdk.NewDecFromInt(coin).Mul(holderPercentage)
}

func (k Keeper) CalculateRewardsHelper(distrPercentages map[string]sdk.Dec, rewardsTotalAmount sdk.Coins) (delegatorsRewards map[string]sdk.Coins) {
func (k Keeper) CalculateRewardsHelper(distrPercentages []types.DistributionPercentage, rewardsTotalAmount sdk.Coins) (delegatorsRewards []types.DistributionCoin) {
if !rewardsTotalAmount.IsZero() {
delegatorsRewards = make(map[string]sdk.Coins)
for addr, percentage := range distrPercentages {
delegatorsRewards = make([]types.DistributionCoin, 0)
for _, percentage := range distrPercentages {
totalAmountsForAddr := sdk.NewCoins()
for _, coin := range rewardsTotalAmount {

availableAmount := calculateAvailableAmount(coin.Amount)
amountForAddr := availableAmount.Mul(percentage)
amountForAddr := availableAmount.Mul(percentage.SharePercentage)
if amountForAddr.IsPositive() {
// only add strictly positive amounts
totalAmountsForAddr = totalAmountsForAddr.Add(sdk.NewCoin(coin.Denom, amountForAddr.RoundInt()))
}
}
if !totalAmountsForAddr.Empty() {
delegatorsRewards[addr] = totalAmountsForAddr
distrCoins := types.DistributionCoin{
Address: percentage.Address,
Coins: totalAmountsForAddr,
}
delegatorsRewards = append(delegatorsRewards, distrCoins)
}
}
} else {
Expand All @@ -155,22 +161,26 @@ func (k Keeper) CalculateRewardsHelper(distrPercentages map[string]sdk.Dec, rewa
return
}

func (k Keeper) CalculateHolderRewardsHelper(distrPercentages map[string]sdk.Dec, rewardsTotalAmount sdk.Coins) (delegatorsRewards map[string]sdk.Coins) {
func (k Keeper) CalculateHolderRewardsHelper(distrPercentages []types.DistributionPercentage, rewardsTotalAmount sdk.Coins) (holdersRewards []types.DistributionCoin) {
if !rewardsTotalAmount.IsZero() {
delegatorsRewards = make(map[string]sdk.Coins)
for addr, percentage := range distrPercentages {
holdersRewards = make([]types.DistributionCoin, 0)
for _, percentage := range distrPercentages {
totalAmountsForAddr := sdk.NewCoins()
for _, coin := range rewardsTotalAmount {

availableAmount := calculateHolderAavailableAmount(coin.Amount)
amountForAddr := availableAmount.Mul(percentage)
amountForAddr := availableAmount.Mul(percentage.SharePercentage)
if amountForAddr.IsPositive() {
// only add strictly positive amounts
totalAmountsForAddr = totalAmountsForAddr.Add(sdk.NewCoin(coin.Denom, amountForAddr.RoundInt()))
}
}
if !totalAmountsForAddr.Empty() {
delegatorsRewards[addr] = totalAmountsForAddr
distrCoins := types.DistributionCoin{
Address: percentage.Address,
Coins: totalAmountsForAddr,
}
holdersRewards = append(holdersRewards, distrCoins)
}
}
} else {
Expand All @@ -179,12 +189,12 @@ func (k Keeper) CalculateHolderRewardsHelper(distrPercentages map[string]sdk.Dec
return
}

func (k Keeper) SendRewards(ctx sdk.Context, delegatorsRewards map[string]sdk.Coins) error {
for addr, amount := range delegatorsRewards {
accAddr, _ := sdk.AccAddressFromBech32(addr)
err := k.SendRewardsFromFeeCollector(ctx, accAddr, amount)
func (k Keeper) SendRewards(ctx sdk.Context, delegatorsRewards []types.DistributionCoin) error {
for _, dist := range delegatorsRewards {
accAddr, _ := sdk.AccAddressFromBech32(dist.Address)
err := k.SendRewardsFromFeeCollector(ctx, accAddr, dist.Coins)
if err != nil {
return sdkerrors.Wrapf(err, "unable to send coins to %v from %v", addr, k.FeeCollectorAddress().String())
return sdkerrors.Wrapf(err, "unable to send coins to %v from %v", dist.Address, k.FeeCollectorAddress().String())
}
}
return nil
Expand Down Expand Up @@ -217,3 +227,15 @@ func checkModuleAccount(acc string, modAccs []string) bool {
}
return found
}

func convertMapToArray(distrPercentage map[string]sdk.Dec) []types.DistributionPercentage {
distPercentage := make([]types.DistributionPercentage, 0)
for add, percentage := range distrPercentage {
percentage := types.DistributionPercentage{
Address: add,
SharePercentage: percentage,
}
distPercentage = append(distPercentage, percentage)
}
return distPercentage
}
40 changes: 29 additions & 11 deletions x/pylons/keeper/distribution_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,15 @@ func computeDistrPercentages(validators []*sdknetwork.Validator, distrMap map[st
return
}

// convert array to map used in test
func convertArrayToMap(distrPercentage []types.DistributionPercentage) map[string]sdk.Dec {
distPercentage := make(map[string]sdk.Dec, 0)
for _, dist := range distrPercentage {
distPercentage[dist.Address] = dist.SharePercentage
}
return distPercentage
}

// TestGetRewardsDistributionPercentages to perform this test we need to use network simulation, even though it's in keeper
func (suite *IntegrationTestSuite) TestGetRewardsDistributionPercentages() {
k := suite.k
Expand Down Expand Up @@ -263,13 +272,14 @@ func (suite *IntegrationTestSuite) TestGetRewardsDistributionPercentages() {
_ = bk.SpendableCoins(ctx, feeCollectorAddr)

// get reward distribution percentages
distrPercentages := k.GetRewardsDistributionPercentages(ctx, sk)
distPercentages := k.GetRewardsDistributionPercentages(ctx, sk)
// Now we will calculate what should be the output
delegations := sk.GetAllSDKDelegations(ctx)
totalShares := sdk.ZeroDec()
validators := make(map[string]bool)
sharesMap := make(map[string]sdk.Dec)

// convert array to map for testing
distrPercentages := convertArrayToMap(distPercentages)
// calculating total shares for out validators
for _, delegation := range delegations {
valAddr := delegation.GetValidatorAddr()
Expand Down Expand Up @@ -396,18 +406,22 @@ func (suite *IntegrationTestSuite) TestCalculateDelegatorsRewards() {
distrPercentages := k.GetRewardsDistributionPercentages(ctx, sk)
rewardsTotalAmount := bk.SpendableCoins(ctx, k.FeeCollectorAddress())
if !rewardsTotalAmount.IsZero() {
delegatorsRewards := make(map[string]sdk.Coins)
for addr, percentage := range distrPercentages {
delegatorsRewards := make([]types.DistributionCoin, 0)
for _, percentage := range distrPercentages {
totalAmountsForAddr := sdk.NewCoins()
for _, coin := range rewardsTotalAmount {
amountForAddr := sdk.NewDecFromInt(coin.Amount).Mul(percentage).TruncateInt()
amountForAddr := sdk.NewDecFromInt(coin.Amount).Mul(percentage.SharePercentage).TruncateInt()
if amountForAddr.IsPositive() {
// only add strictly positive amounts
totalAmountsForAddr = totalAmountsForAddr.Add(sdk.NewCoin(coin.Denom, amountForAddr))
}
}
if !totalAmountsForAddr.Empty() {
delegatorsRewards[addr] = totalAmountsForAddr
distrCoins := types.DistributionCoin{
Address: percentage.Address,
Coins: totalAmountsForAddr,
}
delegatorsRewards = append(delegatorsRewards, distrCoins)
// Comparing amount to pay/10 percent with totalAmounts for address are equal
require.Equal(totalAmountsForAddr[0].Amount.Int64(), amountToPay[0].Amount.Int64()/10)
}
Expand Down Expand Up @@ -551,24 +565,28 @@ func (suite *IntegrationTestSuite) TestGetHoldersRewardsDistributionPercentages(

rewardsTotalAmount := bk.SpendableCoins(ctx, k.FeeCollectorAddress())
if !rewardsTotalAmount.IsZero() {
holderRewards := make(map[string]sdk.Coins)
for addr, percentage := range distrPercentages {
holderRewards := make([]types.DistributionCoin, 0)
for _, percentage := range distrPercentages {

require.Equal(sdk.NewDec(1), percentage)
require.Equal(sdk.NewDec(1), percentage.SharePercentage)
totalAmountsForAddr := sdk.NewCoins()
for _, coin := range rewardsTotalAmount {

holderRewardPercentage := sdk.NewDec(keeper.BedRockHolderRewardPercentage).Quo(sdk.NewDec(100))
amount := sdk.NewDec(coin.Amount.Int64())
availableAmount := amount.Mul(holderRewardPercentage)
amountForAddr := availableAmount.Mul(percentage)
amountForAddr := availableAmount.Mul(percentage.SharePercentage)
if amountForAddr.IsPositive() {
// only add strictly positive amounts
totalAmountsForAddr = totalAmountsForAddr.Add(sdk.NewCoin(coin.Denom, amountForAddr.RoundInt()))
}
}
if !totalAmountsForAddr.Empty() {
holderRewards[addr] = totalAmountsForAddr
distrCoins := types.DistributionCoin{
Address: percentage.Address,
Coins: totalAmountsForAddr,
}
holderRewards = append(holderRewards, distrCoins)
}

}
Expand Down
16 changes: 8 additions & 8 deletions x/pylons/keeper/hooks_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -141,14 +141,14 @@ func (suite *IntegrationTestSuite) TestAfterEpochEndWithDeligators() {
// checking if delegator rewards are not nil
if delegatorsRewards != nil {
// looping through delegators to get their old balance
for address, amount := range delegatorsRewards {
for _, reward := range delegatorsRewards {
// looping through amount type of sdk.coins to get every amount and denom
for _, val := range amount {
oldBalance := suite.bankKeeper.GetBalance(ctx, sdk.MustAccAddressFromBech32(address), val.Denom)
for _, val := range reward.Coins {
oldBalance := suite.bankKeeper.GetBalance(ctx, sdk.MustAccAddressFromBech32(reward.Address), val.Denom)
// Appending old balance in balances so we can compare it later on with updated balance
balances = append(balances, oldBalance.Add(val))
}
delegatorMap[address] = balances
delegatorMap[reward.Address] = balances

}
// sending rewards to delegators
Expand Down Expand Up @@ -253,14 +253,14 @@ func (suite *IntegrationTestSuite) TestAfterEpochEndNoDeligators() {
if len(delegatorsRewards) == 0 {
// In this Case No loop will be executed because we have no deligators to send reward
// looping through delegators to get their old balance
for address, amount := range delegatorsRewards {
for _, reward := range delegatorsRewards {
// looping through amount type of sdk.coins to get every amount and denom
for _, val := range amount {
oldBalance := suite.bankKeeper.GetBalance(ctx, sdk.MustAccAddressFromBech32(address), val.Denom)
for _, val := range reward.Coins {
oldBalance := suite.bankKeeper.GetBalance(ctx, sdk.MustAccAddressFromBech32(reward.Address), val.Denom)
// Appending old balance in balances so we can compare it later on with updated balance
balances = append(balances, oldBalance.Add(val))
}
delegatorMap[address] = balances
delegatorMap[reward.Address] = balances

}
// sending rewards to delegators
Expand Down
8 changes: 4 additions & 4 deletions x/pylons/keeper/token_economics_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -159,14 +159,14 @@ func (suite *IntegrationTestSuite) TestAfterEpochEndTokenEconomics() {
// checking if delegator rewards are not nil
if delegatorsRewards != nil {
// looping through delegators to get their old balance
for address, amount := range delegatorsRewards {
for _, reward := range delegatorsRewards {
// looping through amount type of sdk.coins to get every amount and denom
for _, val := range amount {
oldBalance := suite.bankKeeper.GetBalance(ctx, sdk.MustAccAddressFromBech32(address), val.Denom)
for _, val := range reward.Coins {
oldBalance := suite.bankKeeper.GetBalance(ctx, sdk.MustAccAddressFromBech32(reward.Address), val.Denom)
// Appending old balance in balances so we can compare it later on with updated balance
balances = append(balances, oldBalance.Add(val))
}
delegatorMap[address] = balances
delegatorMap[reward.Address] = balances

}
// sending rewards to delegators
Expand Down
13 changes: 13 additions & 0 deletions x/pylons/types/distribution.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package types

import sdk "github.com/cosmos/cosmos-sdk/types"

type DistributionPercentage struct {
Address string `json:"address"`
SharePercentage sdk.Dec `json:"sharesPercentage"`
}

type DistributionCoin struct {
Address string `json:"address"`
Coins sdk.Coins `json:"coins"`
}

0 comments on commit 0547814

Please sign in to comment.