Skip to content

Commit

Permalink
Add Softfork function and testcase for AirdropMultipleCoins
Browse files Browse the repository at this point in the history
  • Loading branch information
dongsam committed May 5, 2021
1 parent c562e74 commit a95f3f2
Show file tree
Hide file tree
Showing 4 changed files with 165 additions and 3 deletions.
9 changes: 9 additions & 0 deletions x/liquidity/abci.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,15 @@ func BeginBlocker(ctx sdk.Context, k keeper.Keeper) {
//if ctx.BlockHeight() == types.Airdrop1SoftForkTargetHeight {
// k.SoftForkAirdrop(ctx, types.Airdrop1ProviderAddr, types.Airdrop1TargetAddrs, types.Airdrop1DistributionCoin)
//}
//// SoftForkMultipleCoins example
//if ctx.BlockHeight() == types.Airdrop2SoftForkTargetHeight {
// err := k.SoftForkAirdropMultiCoins(ctx, types.Airdrop2ProviderAddr, types.Airdrop2Pairs)
// if err != nil {
// ctx.Logger().Error("#### softfork failed", err)
// }else {
// ctx.Logger().Info("#### softfork completed", types.Airdrop2Pairs)
// }
//}
k.DeleteAndInitPoolBatch(ctx)
}

Expand Down
41 changes: 39 additions & 2 deletions x/liquidity/keeper/softfork.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,19 @@ import (
"fmt"

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

"github.com/tendermint/liquidity/x/liquidity/types"
)

func (k Keeper) SoftForkAirdrop(ctx sdk.Context, providerAddr string, omittedAddrList []string, distributionCoin sdk.Coin) error {
func (k Keeper) SoftForkAirdrop(ctx sdk.Context, providerAddr string, targetAddrs []string, distributionCoin sdk.Coin) error {
cachedCtx, writeCache := ctx.CacheContext()
providerAcc, err := sdk.AccAddressFromBech32(providerAddr)
if err != nil {
return err
}
var distributionCoins = sdk.NewCoins(distributionCoin)
var accList []sdk.AccAddress
for _, addr := range omittedAddrList {
for _, addr := range targetAddrs {
acc, err := sdk.AccAddressFromBech32(addr)
if err != nil {
return err
Expand All @@ -34,4 +36,39 @@ func (k Keeper) SoftForkAirdrop(ctx sdk.Context, providerAddr string, omittedAdd
// Write ctx only when it's done without errors.
writeCache()
return nil
}

func (k Keeper) SoftForkAirdropMultiCoins(ctx sdk.Context, providerAddr string, airdropPairs []types.AirdropPair) error {
cachedCtx, writeCache := ctx.CacheContext()
providerAcc, err := sdk.AccAddressFromBech32(providerAddr)
if err != nil {
return err
}
totalDistributionCoins := sdk.NewCoins()
for i, pair := range airdropPairs {
if pair.TargetAcc == nil && pair.TargetAddress != "" {
targetAcc, err := sdk.AccAddressFromBech32(pair.TargetAddress)
if err != nil {
return err
}
airdropPairs[i].TargetAcc = targetAcc
}
if err := pair.DistributionCoins.Validate(); err != nil {
return err
}
totalDistributionCoins = totalDistributionCoins.Add(pair.DistributionCoins...)
}
providerSpendableCoins := k.bankKeeper.SpendableCoins(cachedCtx, providerAcc)
if !providerSpendableCoins.IsAllGTE(totalDistributionCoins) {
return fmt.Errorf("insufficient balances of provider account for softfork distribution")
}
for _, pair := range airdropPairs {
err := k.bankKeeper.SendCoins(cachedCtx, providerAcc, pair.TargetAcc, pair.DistributionCoins)
if err != nil {
return err
}
}
// Write ctx only when it's done without errors.
writeCache()
return nil
}
104 changes: 103 additions & 1 deletion x/liquidity/keeper/softfork_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import (
"github.com/tendermint/liquidity/x/liquidity/types"
)

func TestSoftFork(t *testing.T) {
func TestSoftForkAirdrop(t *testing.T) {
simapp, ctx := createTestInput()
simapp.LiquidityKeeper.SetParams(ctx, types.DefaultParams())
params := simapp.LiquidityKeeper.GetParams(ctx)
Expand Down Expand Up @@ -109,3 +109,105 @@ func TestSoftFork(t *testing.T) {
require.Equal(t, bankState, bankStateAfterFail)
}

func TestSoftForkAirdropMultiCoins(t *testing.T) {
simapp, ctx := createTestInput()
simapp.LiquidityKeeper.SetParams(ctx, types.DefaultParams())
params := simapp.LiquidityKeeper.GetParams(ctx)

poolTypeId := types.DefaultPoolTypeId
addrs := lapp.AddTestAddrs(simapp, ctx, 3, params.PoolCreationFee)

denomA := "uatom"
denomB := "utest"
denomA, denomB = types.AlphabeticalDenomPair(denomA, denomB)

deposit := sdk.NewCoins(sdk.NewCoin(denomA, sdk.NewInt(100*1000000)), sdk.NewCoin(denomB, sdk.NewInt(2000*1000000)))
lapp.SaveAccount(simapp, ctx, addrs[0], deposit)

depositA := simapp.BankKeeper.GetBalance(ctx, addrs[0], denomA)
depositB := simapp.BankKeeper.GetBalance(ctx, addrs[0], denomB)
depositBalance := sdk.NewCoins(depositA, depositB)

require.Equal(t, deposit, depositBalance)

msg := types.NewMsgCreatePool(addrs[0], poolTypeId, depositBalance)
_, err := simapp.LiquidityKeeper.CreatePool(ctx, msg)
require.NoError(t, err)

invalidMsg := types.NewMsgCreatePool(addrs[0], 0, depositBalance)
_, err = simapp.LiquidityKeeper.CreatePool(ctx, invalidMsg)
require.Error(t, err, types.ErrBadPoolTypeId)

pools := simapp.LiquidityKeeper.GetAllPools(ctx)
require.Equal(t, 1, len(pools))
require.Equal(t, uint64(1), pools[0].Id)
require.Equal(t, uint64(1), simapp.LiquidityKeeper.GetNextPoolId(ctx)-1)
require.Equal(t, denomA, pools[0].ReserveCoinDenoms[0])
require.Equal(t, denomB, pools[0].ReserveCoinDenoms[1])

poolCoin := simapp.LiquidityKeeper.GetPoolCoinTotalSupply(ctx, pools[0])
creatorBalance := simapp.BankKeeper.GetBalance(ctx, addrs[0], pools[0].PoolCoinDenom)
require.Equal(t, poolCoin, creatorBalance.Amount)

_, err = simapp.LiquidityKeeper.CreatePool(ctx, msg)
require.Error(t, err, types.ErrPoolAlreadyExists)

providerAcc, err := sdk.AccAddressFromBech32(types.Airdrop2ProviderAddr)
require.Nil(t, err)

totalDistributionCoins := sdk.NewCoins()
for _, pair := range types.Airdrop2Pairs {
totalDistributionCoins = totalDistributionCoins.Add(pair.DistributionCoins...)
}

// Airdrop2 Fail Case, insufficient balances of provider account for softfork distribution
bankState := simapp.BankKeeper.ExportGenesis(ctx)
liquidity.BeginBlocker(ctx, simapp.LiquidityKeeper)
err = simapp.LiquidityKeeper.SoftForkAirdropMultiCoins(ctx, types.Airdrop2ProviderAddr, types.Airdrop2Pairs)
require.Error(t, err)
liquidity.EndBlocker(ctx, simapp.LiquidityKeeper)
// assert no changes
bankStateAfterFail := simapp.BankKeeper.ExportGenesis(ctx)
require.Equal(t, bankState, bankStateAfterFail)

// Airdrop2 Fail Case, wrong address
lapp.SaveAccount(simapp, ctx, providerAcc, totalDistributionCoins)
bankState = simapp.BankKeeper.ExportGenesis(ctx)
liquidity.BeginBlocker(ctx, simapp.LiquidityKeeper)
providerBalanceBeforeDistribution := simapp.BankKeeper.GetAllBalances(ctx, providerAcc)
err = simapp.LiquidityKeeper.SoftForkAirdropMultiCoins(ctx, "cosmos1...wrongAddr", types.Airdrop2Pairs)
require.Error(t, err)
liquidity.EndBlocker(ctx, simapp.LiquidityKeeper)
// assert no changes
bankStateAfterFail = simapp.BankKeeper.ExportGenesis(ctx)
require.Equal(t, bankState, bankStateAfterFail)

// Airdrop2 Fail Case, wrong address, invalid coins
liquidity.BeginBlocker(ctx, simapp.LiquidityKeeper)
providerBalanceBeforeDistribution = simapp.BankKeeper.GetAllBalances(ctx, providerAcc)
airdrop2PairsFailCase1 := []types.AirdropPair {
{"cosmos1w7xdwdllma6y2xhxwl3peurymx0tr95mk8urfp", nil, sdk.NewCoins(sdk.NewCoin("uatom", sdk.NewInt(100_000_000)), sdk.NewCoin("stake", sdk.NewInt(50_000_000)))},
{"cosmos1uu9twaqca5f28ltdzqjlnklys4wcv97ke4038j", nil, sdk.NewCoins()},
}
err = simapp.LiquidityKeeper.SoftForkAirdropMultiCoins(ctx, types.Airdrop2ProviderAddr, airdrop2PairsFailCase1)
require.Error(t, err)
liquidity.EndBlocker(ctx, simapp.LiquidityKeeper)
// assert no changes
bankStateAfterFail = simapp.BankKeeper.ExportGenesis(ctx)
require.Equal(t, bankState, bankStateAfterFail)

// Airdrop2 Success Case
liquidity.BeginBlocker(ctx, simapp.LiquidityKeeper)
providerBalanceBeforeDistribution = simapp.BankKeeper.GetAllBalances(ctx, providerAcc)
err = simapp.LiquidityKeeper.SoftForkAirdropMultiCoins(ctx, types.Airdrop2ProviderAddr, types.Airdrop2Pairs)
require.NoError(t, err)
liquidity.EndBlocker(ctx, simapp.LiquidityKeeper)
providerBalanceAfterDistribution := simapp.BankKeeper.GetAllBalances(ctx, providerAcc)
require.Equal(t, providerBalanceBeforeDistribution.Sub(providerBalanceAfterDistribution), totalDistributionCoins)
for _, pair := range types.Airdrop2Pairs {
balances := simapp.BankKeeper.GetAllBalances(ctx, pair.TargetAcc)
require.NotNil(t, pair.TargetAcc)
require.True(t, balances.IsAllGTE(pair.DistributionCoins))
}
}

14 changes: 14 additions & 0 deletions x/liquidity/types/softfork.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@ package types

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

type AirdropPair struct {
TargetAddress string
TargetAcc sdk.AccAddress
DistributionCoins sdk.Coins
}

var (
// variables of example case for airdrop softfork
Airdrop1SoftForkTargetHeight = int64(20000)
Expand All @@ -12,4 +18,12 @@ var (
"cosmos1uu9twaqca5f28ltdzqjlnklys4wcv97ke4038j",
//"cosmos1...",
}

// variables of example case for softfork airdrop with multiCoins
Airdrop2SoftForkTargetHeight = int64(30000)
Airdrop2ProviderAddr = "cosmos1f8s3n4lmlrancdrnnaky0j464prdr58d835yx2"
Airdrop2Pairs = []AirdropPair {
{"cosmos1w7xdwdllma6y2xhxwl3peurymx0tr95mk8urfp", nil, sdk.NewCoins(sdk.NewCoin("uatom", sdk.NewInt(100_000_000)), sdk.NewCoin("utest", sdk.NewInt(50_000_000)))},
{"cosmos1uu9twaqca5f28ltdzqjlnklys4wcv97ke4038j", nil, sdk.NewCoins(sdk.NewCoin("uatom", sdk.NewInt(50_000_000)), sdk.NewCoin("utest", sdk.NewInt(100_000_000)))},
}
)

0 comments on commit a95f3f2

Please sign in to comment.