Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
yun-yeo committed May 21, 2022
2 parents b88f75a + 87c755d commit bbe0a0b
Show file tree
Hide file tree
Showing 2 changed files with 150 additions and 1 deletion.
60 changes: 59 additions & 1 deletion app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import (
authtx "github.com/cosmos/cosmos-sdk/x/auth/tx"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
"github.com/cosmos/cosmos-sdk/x/auth/vesting"
vestingexported "github.com/cosmos/cosmos-sdk/x/auth/vesting/exported"
vestingtypes "github.com/cosmos/cosmos-sdk/x/auth/vesting/types"
"github.com/cosmos/cosmos-sdk/x/authz"
authzkeeper "github.com/cosmos/cosmos-sdk/x/authz/keeper"
Expand Down Expand Up @@ -710,7 +711,12 @@ func (app *TerraApp) InitChainer(ctx sdk.Context, req abci.RequestInitChain) abc
panic(err)
}
app.UpgradeKeeper.SetModuleVersionMap(ctx, app.mm.GetVersionMap())
return app.mm.InitGenesis(ctx, app.appCodec, genesisState)
res := app.mm.InitGenesis(ctx, app.appCodec, genesisState)

// stake all vesting tokens
app.enforceStakingForVestingTokens(ctx, genesisState)

return res
}

// LoadHeight loads a particular height
Expand Down Expand Up @@ -855,3 +861,55 @@ func initParamsKeeper(appCodec codec.BinaryCodec, legacyAmino *codec.LegacyAmino

return paramsKeeper
}

// enforceStakingForVestingTokens enforce vesting tokens to be staked
// CONTRACT: validator's gentx account must not be a vesting account
func (app *TerraApp) enforceStakingForVestingTokens(ctx sdk.Context, genesisState GenesisState) {

var authState authtypes.GenesisState
app.appCodec.MustUnmarshalJSON(genesisState[authtypes.ModuleName], &authState)

validators := app.StakingKeeper.GetValidators(ctx, app.StakingKeeper.MaxValidators(ctx))
validatorLen := len(validators)

// ignore when validator len is zero
if validatorLen == 0 {
return
}

i := 0
stakeSplitCondition := sdk.NewInt(1_000_000_000_000)
for _, acc := range authState.GetAccounts() {
var account authtypes.AccountI
if err := app.InterfaceRegistry().UnpackAny(acc, &account); err != nil {
panic(err)
}

if vestingAcc, ok := account.(vestingexported.VestingAccount); ok {
amt := vestingAcc.GetOriginalVesting().AmountOf(app.StakingKeeper.BondDenom(ctx))

// if a vesting account has more staking token than `stakeSplitCondition`,
// split staking balance to distribute staking power evenly
// Ex) 2_200_000_000_000
// stake 1_000_000_000_000 to val1
// stake 1_000_000_000_000 to val2
// stake 200_000_000_000 to val3
for ; amt.GTE(sdk.OneInt()); amt = amt.Sub(stakeSplitCondition) {
if _, err := app.StakingKeeper.Delegate(
ctx,
vestingAcc.GetAddress(),
sdk.MinInt(amt, stakeSplitCondition),
stakingtypes.Unbonded,
validators[i%validatorLen],
true,
); err != nil {
panic(err)
}

// increase index only when staking happened
i++
}

}
}
}
91 changes: 91 additions & 0 deletions app/app_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,15 @@ import (
dbm "github.com/tendermint/tm-db"
"github.com/terra-money/core/app/wasmconfig"

"github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1"
"github.com/cosmos/cosmos-sdk/simapp"
"github.com/cosmos/cosmos-sdk/tests/mocks"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/module"
"github.com/cosmos/cosmos-sdk/x/auth"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
"github.com/cosmos/cosmos-sdk/x/auth/vesting"
vestingtypes "github.com/cosmos/cosmos-sdk/x/auth/vesting/types"
authzmodule "github.com/cosmos/cosmos-sdk/x/authz/module"
"github.com/cosmos/cosmos-sdk/x/bank"
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
Expand All @@ -34,6 +38,8 @@ import (
paramstypes "github.com/cosmos/cosmos-sdk/x/params/types"
"github.com/cosmos/cosmos-sdk/x/slashing"
"github.com/cosmos/cosmos-sdk/x/staking"
"github.com/cosmos/cosmos-sdk/x/staking/teststaking"
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
"github.com/cosmos/cosmos-sdk/x/upgrade"

ica "github.com/cosmos/ibc-go/v3/modules/apps/27-interchain-accounts"
Expand All @@ -44,6 +50,21 @@ import (
"github.com/CosmWasm/wasmd/x/wasm"
)

var (
priv1 = secp256k1.GenPrivKey()
priv2 = secp256k1.GenPrivKey()
priv3 = secp256k1.GenPrivKey()
priv4 = secp256k1.GenPrivKey()
pk1 = priv1.PubKey()
pk2 = priv2.PubKey()
pk3 = priv3.PubKey()
pk4 = priv4.PubKey()
addr1 = sdk.AccAddress(pk1.Address())
addr2 = sdk.AccAddress(pk2.Address())
addr3 = sdk.AccAddress(pk3.Address())
addr4 = sdk.AccAddress(pk4.Address())
)

func TestSimAppExportAndBlockedAddrs(t *testing.T) {
encCfg := MakeEncodingConfig()
db := dbm.NewMemDB()
Expand Down Expand Up @@ -207,3 +228,73 @@ func TestGetKey(t *testing.T) {
require.NotEmpty(t, app.GetTKey(paramstypes.TStoreKey))
require.NotEmpty(t, app.GetMemKey(capabilitytypes.MemStoreKey))
}

func TestSimAppEnforceStakingForVestingTokens(t *testing.T) {
genAccounts := authtypes.GenesisAccounts{
vestingtypes.NewContinuousVestingAccount(
authtypes.NewBaseAccountWithAddress(addr1),
sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(2_500_000_000_000))),
1660000000,
1670000000,
),
vestingtypes.NewContinuousVestingAccount(
authtypes.NewBaseAccountWithAddress(addr2),
sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(4_500_000_000_000))),
1660000000,
1670000000,
),
authtypes.NewBaseAccountWithAddress(addr3),
authtypes.NewBaseAccountWithAddress(addr4),
}
app := SetupWithGenesisAccounts(genAccounts, []banktypes.Balance{
{
Address: addr1.String(),
Coins: sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(2_500_000_000_000))),
},
{
Address: addr2.String(),
Coins: sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(4_500_000_000_000))),
},
{
Address: addr3.String(),
Coins: sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(1_000_000))),
},
{
Address: addr4.String(),
Coins: sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, sdk.NewInt(1_000_000))),
},
}...)

ctx := app.NewContext(true, tmproto.Header{Height: app.LastBlockHeight()})

genesisState := make(GenesisState)
genesisState[authtypes.ModuleName] = app.appCodec.MustMarshalJSON(authtypes.NewGenesisState(authtypes.DefaultParams(), genAccounts))

tstaking := teststaking.NewHelper(t, ctx, app.StakingKeeper)

// create validator with 50% commission
pubkeys := simapp.CreateTestPubKeys(2)
valAddrs := simapp.ConvertAddrsToValAddrs([]sdk.AccAddress{addr3, addr4})
tstaking.Commission = stakingtypes.NewCommissionRates(sdk.NewDecWithPrec(5, 1), sdk.NewDecWithPrec(5, 1), sdk.NewDec(0))
tstaking.CreateValidator(sdk.ValAddress(addr3), pubkeys[0], sdk.NewInt(1_000_000), true)
tstaking.CreateValidator(sdk.ValAddress(addr4), pubkeys[1], sdk.NewInt(1_000_000), true)
vals := []stakingtypes.ValidatorI{app.StakingKeeper.Validator(ctx, valAddrs[0]), app.StakingKeeper.Validator(ctx, valAddrs[1])}
require.NotNil(t, vals[0])
require.NotNil(t, vals[1])

app.enforceStakingForVestingTokens(ctx, genesisState)
delegations := app.StakingKeeper.GetAllDelegations(ctx)
sharePerValidators := make(map[string]sdk.Dec)

for _, del := range delegations {
if val, found := sharePerValidators[del.ValidatorAddress]; !found {
sharePerValidators[del.ValidatorAddress] = del.GetShares()
} else {
sharePerValidators[del.ValidatorAddress] = val.Add(del.GetShares())
}
}

for _, share := range sharePerValidators {
require.Equal(t, sdk.NewDec(3_500_001_000_000), share)
}
}

0 comments on commit bbe0a0b

Please sign in to comment.