mirror of
				https://github.com/0glabs/0g-chain.git
				synced 2025-10-31 23:08:32 +00:00 
			
		
		
		
	Add swp token distribution (#1003)
* implement swp airdrop to usdx depositors to hard * verify swp airdrop amount, total supply, affected users * remove unused test code * add map as go file * update tests to use stored variable * re-add snapshot test * update snapshot testdata * remove unused code for generating swp airdrop map * remove snapshot test * add swp token distribution * bump test timeouts * address review comments * use global variables to simplify testing assertions on swp supply * optional: swp migration test and small refactor (#1005) * add test to ensure balances are not decreased * simplify slice manipulation * bump context deadline in circleci Co-authored-by: Ruaridh <rhuairahrighairidh@users.noreply.github.com>
This commit is contained in:
		
							parent
							
								
									346501aa58
								
							
						
					
					
						commit
						cac7398120
					
				| @ -67,13 +67,14 @@ jobs: | ||||
|             - go-mod-v2-{{ checksum "go.sum" }} | ||||
|       - run: | ||||
|           name: Run tests | ||||
|           no_output_timeout: 30m | ||||
|           command: | | ||||
|             export VERSION="$(git describe --tags --long | sed 's/v\(.*\)/\1/')" | ||||
|             export GO111MODULE=on | ||||
|             mkdir -p /tmp/logs /tmp/workspace/profiles | ||||
|             for pkg in $(go list ./... | grep -v -P 'simulation|migrate(?!\/v0_15)|contrib' | circleci tests split); do | ||||
|               id=$(echo "$pkg" | sed 's|[/.]|_|g') | ||||
|               go test -mod=readonly -timeout 8m -race -coverprofile=/tmp/workspace/profiles/$id.out -covermode=atomic -tags='ledger test_ledger_mock' "$pkg" | tee "/tmp/logs/$id-$RANDOM.log" | ||||
|               go test -mod=readonly -timeout 20m -race -coverprofile=/tmp/workspace/profiles/$id.out -covermode=atomic -tags='ledger test_ledger_mock' "$pkg" | tee "/tmp/logs/$id-$RANDOM.log" | ||||
|             done | ||||
|       - persist_to_workspace: | ||||
|           root: /tmp/workspace | ||||
|  | ||||
| @ -18,16 +18,15 @@ import ( | ||||
| 	v0_15committee "github.com/kava-labs/kava/x/committee/types" | ||||
| 	v0_14incentive "github.com/kava-labs/kava/x/incentive/legacy/v0_14" | ||||
| 	v0_15incentive "github.com/kava-labs/kava/x/incentive/types" | ||||
| 	"github.com/kava-labs/kava/x/kavadist" | ||||
| 	v0_15swap "github.com/kava-labs/kava/x/swap/types" | ||||
| 	v0_14validator_vesting "github.com/kava-labs/kava/x/validator-vesting" | ||||
| ) | ||||
| 
 | ||||
| var ( | ||||
| 	// TODO: update GenesisTime and chain-id for kava-8 launch
 | ||||
| 	GenesisTime = time.Date(2021, 8, 30, 15, 0, 0, 0, time.UTC) | ||||
| 	GenesisTime = time.Date(2021, 8, 30, 15, 0, 0, 0, time.UTC) // 1630335600
 | ||||
| 	ChainID     = "kava-8" | ||||
| 	// TODO: update SWP reward per second amount before production
 | ||||
| 	// TODO: add swap tokens to kavadist module account
 | ||||
| 	// TODO: update SWP reward per second amount before production
 | ||||
| 	SwpDelegatorRewardsPerSecond         = sdk.NewCoin("swp", sdk.OneInt()) | ||||
| 	SwpLiquidityProviderRewardsPerSecond = sdk.NewCoin("swp", sdk.OneInt()) | ||||
| @ -112,10 +111,12 @@ func makeV014Codec() *codec.Codec { | ||||
| func Auth(cdc *codec.Codec, genesisState auth.GenesisState, genesisTime time.Time) auth.GenesisState { | ||||
| 	genesisStateWithAccountsMigrated := MigrateAccounts(genesisState, genesisTime) | ||||
| 	genesisStateWithSwpAirdrop := ApplySwpAirdrop(cdc, genesisStateWithAccountsMigrated) | ||||
| 	genesisStateWithSwpDistribution := DistributeSwpTokens(genesisStateWithSwpAirdrop) | ||||
| 
 | ||||
| 	return genesisStateWithSwpAirdrop | ||||
| 	return genesisStateWithSwpDistribution | ||||
| } | ||||
| 
 | ||||
| // ApplySwpAirdrop airdrops 1,000,000 SWP tokens to USDX depositors to HARD at block 1543671
 | ||||
| func ApplySwpAirdrop(cdc *codec.Codec, genesisState auth.GenesisState) auth.GenesisState { | ||||
| 	accounts := make([]authexported.GenesisAccount, len(genesisState.Accounts)) | ||||
| 	migratedGenesisState := auth.NewGenesisState(genesisState.Params, accounts) | ||||
| @ -123,13 +124,17 @@ func ApplySwpAirdrop(cdc *codec.Codec, genesisState auth.GenesisState) auth.Gene | ||||
| 	cdc.MustUnmarshalJSON([]byte(swpAirdropMap), &swpAirdrop) | ||||
| 	for i, acc := range genesisState.Accounts { | ||||
| 		if swpReward, ok := swpAirdrop[acc.GetAddress().String()]; ok { | ||||
| 			acc.SetCoins(acc.GetCoins().Add(swpReward)) | ||||
| 			err := acc.SetCoins(acc.GetCoins().Add(swpReward)) | ||||
| 			if err != nil { | ||||
| 				panic(err) | ||||
| 			} | ||||
| 		} | ||||
| 		accounts[i] = authexported.GenesisAccount(acc) | ||||
| 	} | ||||
| 	return migratedGenesisState | ||||
| } | ||||
| 
 | ||||
| // MigrateAccounts removes expired vesting periods from account state
 | ||||
| func MigrateAccounts(genesisState auth.GenesisState, genesisTime time.Time) auth.GenesisState { | ||||
| 	accounts := make([]authexported.GenesisAccount, len(genesisState.Accounts)) | ||||
| 	migratedGenesisState := auth.NewGenesisState(genesisState.Params, accounts) | ||||
| @ -141,6 +146,104 @@ func MigrateAccounts(genesisState auth.GenesisState, genesisTime time.Time) auth | ||||
| 	return migratedGenesisState | ||||
| } | ||||
| 
 | ||||
| // global variables for swp distribution
 | ||||
| var ( | ||||
| 	SwpEcoSystemAddr           = mustAccAddressFromBech32("kava174crgzk006lj39s258gjxkh0p9tmmq8ugdcg0n") | ||||
| 	SwpTreasuryAddr            = mustAccAddressFromBech32("kava1w56wrusdnrv4tvn86eyam65wwhqatmsqg9fxjm") | ||||
| 	SwpTeamAddr                = mustAccAddressFromBech32("kava129eqnykzkc5ceyq9sv7ltxev22y8qwm94kr0ew") | ||||
| 	KavaDistAddr               = supply.NewModuleAddress(kavadist.KavaDistMacc) | ||||
| 	SwpTreasuryCoins           = sdk.NewCoin("swp", sdk.NewInt(62500000000000)) | ||||
| 	SwpTreasuryOriginalVesting = sdk.NewCoin("swp", sdk.NewInt(46875000000000)) | ||||
| 	KavaDistCoins              = sdk.NewCoin("swp", sdk.NewInt(137500000e6)) | ||||
| 	EcoSystemCoins             = sdk.NewCoin("swp", sdk.NewInt(11500000000000)) | ||||
| 	SwpTeamCoins               = sdk.NewCoin("swp", sdk.NewInt(37500000000000)) | ||||
| ) | ||||
| 
 | ||||
| // DistributeSwpTokens sets the initial distribution of swp tokens according to the proposed token supply schedule in prop 59
 | ||||
| func DistributeSwpTokens(genesisState auth.GenesisState) auth.GenesisState { | ||||
| 
 | ||||
| 	// add SWP incentives (LP, Kava stakers) to kavadist module account
 | ||||
| 	accounts := make([]authexported.GenesisAccount, len(genesisState.Accounts)) | ||||
| 	for i, acc := range genesisState.Accounts { | ||||
| 		if acc.GetAddress().Equals(KavaDistAddr) { | ||||
| 			err := acc.SetCoins(acc.GetCoins().Add(KavaDistCoins)) | ||||
| 			if err != nil { | ||||
| 				panic(err) | ||||
| 			} | ||||
| 		} | ||||
| 		accounts[i] = authexported.GenesisAccount(acc) | ||||
| 
 | ||||
| 	} | ||||
| 
 | ||||
| 	// Add ecosystem account
 | ||||
| 	swpEcosystemBacc := auth.NewBaseAccountWithAddress(SwpEcoSystemAddr) | ||||
| 	// 11.5M because 1M has already been airdropped
 | ||||
| 	err := swpEcosystemBacc.SetCoins(sdk.NewCoins(EcoSystemCoins)) | ||||
| 	if err != nil { | ||||
| 		panic(err) | ||||
| 	} | ||||
| 
 | ||||
| 	// Add team vesting account
 | ||||
| 	swpTeamBacc := auth.NewBaseAccountWithAddress(SwpTeamAddr) | ||||
| 	err = swpTeamBacc.SetCoins(sdk.NewCoins(SwpTeamCoins)) | ||||
| 	if err != nil { | ||||
| 		panic(err) | ||||
| 	} | ||||
| 	swpTeamBva, err := vesting.NewBaseVestingAccount(&swpTeamBacc, sdk.NewCoins(SwpTeamCoins), 1693407600) | ||||
| 	if err != nil { | ||||
| 		panic(err) | ||||
| 	} | ||||
| 	swpTeamTokenSchedule := []sdk.Coin{ | ||||
| 		sdk.NewCoin("swp", sdk.NewInt(18750000000000)), | ||||
| 		sdk.NewCoin("swp", sdk.NewInt(4687500000000)), | ||||
| 		sdk.NewCoin("swp", sdk.NewInt(4687500000000)), | ||||
| 		sdk.NewCoin("swp", sdk.NewInt(4687500000000)), | ||||
| 		sdk.NewCoin("swp", sdk.NewInt(4687500000000)), | ||||
| 	} | ||||
| 
 | ||||
| 	swpTeamVestingLengths := []int64{31536000, 7948800, 7776000, 7948800, 7862400} | ||||
| 	swpTeamVestingPeriods := vesting.Periods{} | ||||
| 	for i, vestingCoin := range swpTeamTokenSchedule { | ||||
| 		period := vesting.Period{Length: swpTeamVestingLengths[i], Amount: sdk.NewCoins(vestingCoin)} | ||||
| 		swpTeamVestingPeriods = append(swpTeamVestingPeriods, period) | ||||
| 	} | ||||
| 	swpTeamVestingAccount := vesting.NewPeriodicVestingAccountRaw(swpTeamBva, GenesisTime.Unix(), swpTeamVestingPeriods) | ||||
| 
 | ||||
| 	// Add treasury vesting account
 | ||||
| 	swpTreasuryBacc := auth.NewBaseAccountWithAddress(SwpTreasuryAddr) | ||||
| 
 | ||||
| 	err = swpTreasuryBacc.SetCoins(sdk.NewCoins(SwpTreasuryCoins)) | ||||
| 	if err != nil { | ||||
| 		panic(err) | ||||
| 	} | ||||
| 
 | ||||
| 	swpTreasuryBva, err := vesting.NewBaseVestingAccount(&swpTreasuryBacc, sdk.NewCoins(SwpTreasuryOriginalVesting), 1693407600) | ||||
| 	if err != nil { | ||||
| 		panic(err) | ||||
| 	} | ||||
| 	swpTreasuryTokenSchedule := []sdk.Coin{ | ||||
| 		sdk.NewCoin("swp", sdk.NewInt(5859375e6)), | ||||
| 		sdk.NewCoin("swp", sdk.NewInt(5859375e6)), | ||||
| 		sdk.NewCoin("swp", sdk.NewInt(5859375e6)), | ||||
| 		sdk.NewCoin("swp", sdk.NewInt(5859375e6)), | ||||
| 		sdk.NewCoin("swp", sdk.NewInt(5859375e6)), | ||||
| 		sdk.NewCoin("swp", sdk.NewInt(5859375e6)), | ||||
| 		sdk.NewCoin("swp", sdk.NewInt(5859375e6)), | ||||
| 		sdk.NewCoin("swp", sdk.NewInt(5859375e6)), | ||||
| 	} | ||||
| 	swpTreasuryVestingLengths := []int64{7948800, 7776000, 7948800, 7862400, 7948800, 7776000, 7948800, 7862400} | ||||
| 	swpTreasuryVestingPeriods := vesting.Periods{} | ||||
| 	for i, vestingCoin := range swpTreasuryTokenSchedule { | ||||
| 		period := vesting.Period{Length: swpTreasuryVestingLengths[i], Amount: sdk.NewCoins(vestingCoin)} | ||||
| 		swpTreasuryVestingPeriods = append(swpTreasuryVestingPeriods, period) | ||||
| 	} | ||||
| 	swpTreasuryVestingAccount := vesting.NewPeriodicVestingAccountRaw(swpTreasuryBva, GenesisTime.Unix(), swpTreasuryVestingPeriods) | ||||
| 
 | ||||
| 	accounts = append(accounts, &swpEcosystemBacc, swpTeamVestingAccount, swpTreasuryVestingAccount) | ||||
| 
 | ||||
| 	return auth.NewGenesisState(genesisState.Params, accounts) | ||||
| } | ||||
| 
 | ||||
| // Committee migrates from a v0.14 committee genesis state to a v0.15 committee genesis state
 | ||||
| func Committee(genesisState v0_14committee.GenesisState) v0_15committee.GenesisState { | ||||
| 
 | ||||
| @ -379,3 +482,12 @@ func Swap() v0_15swap.GenesisState { | ||||
| 	params := v0_15swap.NewParams(pools, fee) | ||||
| 	return v0_15swap.NewGenesisState(params, v0_15swap.DefaultPoolRecords, v0_15swap.DefaultShareRecords) | ||||
| } | ||||
| 
 | ||||
| func mustAccAddressFromBech32(bech32Addr string) sdk.AccAddress { | ||||
| 	app.SetBech32AddressPrefixes(sdk.GetConfig()) | ||||
| 	addr, err := sdk.AccAddressFromBech32(bech32Addr) | ||||
| 	if err != nil { | ||||
| 		panic(err) | ||||
| 	} | ||||
| 	return addr | ||||
| } | ||||
|  | ||||
| @ -189,6 +189,33 @@ func TestAuth_AccountConversion(t *testing.T) { | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func TestAuth_Regression_BalancesEqual(t *testing.T) { | ||||
| 	bz, err := ioutil.ReadFile(filepath.Join("testdata", "block-1543671-auth-state.json")) | ||||
| 	require.NoError(t, err) | ||||
| 
 | ||||
| 	cdc := app.MakeCodec() | ||||
| 
 | ||||
| 	var originalGenesisState auth.GenesisState | ||||
| 	cdc.MustUnmarshalJSON(bz, &originalGenesisState) | ||||
| 
 | ||||
| 	var genesisState auth.GenesisState | ||||
| 	cdc.MustUnmarshalJSON(bz, &genesisState) | ||||
| 
 | ||||
| 	genesisState = Auth(cdc, genesisState, GenesisTime) | ||||
| 
 | ||||
| 	for i, oldAcc := range originalGenesisState.Accounts { | ||||
| 		acc := genesisState.Accounts[i] | ||||
| 
 | ||||
| 		// total owned coins does not change, despite additional swp tokens
 | ||||
| 		swpBalance := sdk.NewCoins(sdk.NewCoin("swp", acc.GetCoins().AmountOf("swp"))) | ||||
| 		require.Equal(t, oldAcc.GetCoins(), acc.GetCoins().Sub(swpBalance), "expected base coins to not change") | ||||
| 
 | ||||
| 		// ensure spendable coins at genesis time is equal, despite additional swp tokens
 | ||||
| 		swpBalance = sdk.NewCoins(sdk.NewCoin("swp", acc.SpendableCoins(GenesisTime).AmountOf("swp"))) | ||||
| 		require.Equal(t, oldAcc.SpendableCoins(GenesisTime), acc.SpendableCoins(GenesisTime).Sub(swpBalance), "expected spendable coins to not change") | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func TestAuth_MakeAirdropMap(t *testing.T) { | ||||
| 	cdc := app.MakeCodec() | ||||
| 	aidropTokenAmount := sdk.NewInt(1000000000000) | ||||
| @ -225,9 +252,8 @@ func TestAuth_TestAllDepositorsIncluded(t *testing.T) { | ||||
| 	require.Equal(t, depositorsInSnapShot, len(keys)) | ||||
| } | ||||
| 
 | ||||
| func TestAuth_SwpSupply(t *testing.T) { | ||||
| func TestAuth_SwpSupply_AfterAirdrop(t *testing.T) { | ||||
| 	swpSupply := sdk.NewCoin("swp", sdk.ZeroInt()) | ||||
| 	// TODO update when additional swp are added to migration, final supply should be 250M at genesis
 | ||||
| 	expectedSwpSupply := sdk.NewCoin("swp", sdk.NewInt(1000000000000)) | ||||
| 	bz, err := ioutil.ReadFile(filepath.Join("testdata", "block-1543671-auth-state.json")) | ||||
| 	require.NoError(t, err) | ||||
| @ -236,6 +262,28 @@ func TestAuth_SwpSupply(t *testing.T) { | ||||
| 	cdc := app.MakeCodec() | ||||
| 	cdc.MustUnmarshalJSON(bz, &genesisState) | ||||
| 
 | ||||
| 	migratedGenesisState := ApplySwpAirdrop(cdc, genesisState) | ||||
| 
 | ||||
| 	for _, acc := range migratedGenesisState.Accounts { | ||||
| 		swpAmount := acc.GetCoins().AmountOf("swp") | ||||
| 		if swpAmount.IsPositive() { | ||||
| 			swpCoin := sdk.NewCoin("swp", swpAmount) | ||||
| 			swpSupply = swpSupply.Add(swpCoin) | ||||
| 		} | ||||
| 	} | ||||
| 	require.Equal(t, expectedSwpSupply, swpSupply) | ||||
| } | ||||
| 
 | ||||
| func TestAuth_SwpSupply_TotalSupply(t *testing.T) { | ||||
| 	swpSupply := sdk.NewCoin("swp", sdk.ZeroInt()) | ||||
| 	expectedSwpSupply := sdk.NewCoin("swp", sdk.NewInt(250000000e6)) | ||||
| 	bz, err := ioutil.ReadFile(filepath.Join("testdata", "block-1543671-auth-state.json")) | ||||
| 	require.NoError(t, err) | ||||
| 
 | ||||
| 	var genesisState auth.GenesisState | ||||
| 	cdc := app.MakeCodec() | ||||
| 	cdc.MustUnmarshalJSON(bz, &genesisState) | ||||
| 
 | ||||
| 	migratedGenesisState := Auth(cdc, genesisState, GenesisTime) | ||||
| 
 | ||||
| 	for _, acc := range migratedGenesisState.Accounts { | ||||
| @ -247,3 +295,59 @@ func TestAuth_SwpSupply(t *testing.T) { | ||||
| 	} | ||||
| 	require.Equal(t, expectedSwpSupply, swpSupply) | ||||
| } | ||||
| 
 | ||||
| func TestAuth_SwpSupply_SpendableCoins(t *testing.T) { | ||||
| 	bz, err := ioutil.ReadFile(filepath.Join("testdata", "block-1543671-auth-state.json")) | ||||
| 	require.NoError(t, err) | ||||
| 
 | ||||
| 	var genesisState auth.GenesisState | ||||
| 	cdc := app.MakeCodec() | ||||
| 	cdc.MustUnmarshalJSON(bz, &genesisState) | ||||
| 
 | ||||
| 	swpTreasuryExpectedSpendableCoins := sdk.NewCoins(SwpTreasuryCoins.Sub(SwpTreasuryOriginalVesting)) | ||||
| 	foundTreasury := false | ||||
| 
 | ||||
| 	swpTeamExpectedSpendableCoins := sdk.Coins(nil) | ||||
| 	foundTeam := false | ||||
| 
 | ||||
| 	kavaDistExpectedSpendableCoins := KavaDistCoins | ||||
| 	foundKavadist := false | ||||
| 
 | ||||
| 	swpEcosystemExpectedSpendableCoins := sdk.NewCoins(EcoSystemCoins) | ||||
| 	foundEcosystem := false | ||||
| 
 | ||||
| 	migratedGenesisState := Auth(cdc, genesisState, GenesisTime) | ||||
| 
 | ||||
| 	for _, acc := range migratedGenesisState.Accounts { | ||||
| 		if acc.GetAddress().Equals(SwpTreasuryAddr) { | ||||
| 			foundTreasury = true | ||||
| 			pva, ok := acc.(*vesting.PeriodicVestingAccount) | ||||
| 			require.True(t, ok) | ||||
| 			spendableCoins := pva.SpendableCoins(GenesisTime) | ||||
| 			require.Equal(t, swpTreasuryExpectedSpendableCoins, spendableCoins) | ||||
| 		} | ||||
| 		if acc.GetAddress().Equals(SwpTeamAddr) { | ||||
| 			foundTeam = true | ||||
| 			pva, ok := acc.(*vesting.PeriodicVestingAccount) | ||||
| 			require.True(t, ok) | ||||
| 			spendableCoins := pva.SpendableCoins(GenesisTime) | ||||
| 			require.Equal(t, swpTeamExpectedSpendableCoins, spendableCoins) | ||||
| 		} | ||||
| 		if acc.GetAddress().Equals(KavaDistAddr) { | ||||
| 			foundKavadist = true | ||||
| 			spendableCoins := acc.SpendableCoins(GenesisTime) | ||||
| 			spendableSwp := sdk.NewCoin("swp", spendableCoins.AmountOf("swp")) | ||||
| 			require.Equal(t, kavaDistExpectedSpendableCoins, spendableSwp) | ||||
| 		} | ||||
| 		if acc.GetAddress().Equals(SwpEcoSystemAddr) { | ||||
| 			foundEcosystem = true | ||||
| 			spendableCoins := acc.SpendableCoins(GenesisTime) | ||||
| 			require.Equal(t, swpEcosystemExpectedSpendableCoins, spendableCoins) | ||||
| 		} | ||||
| 	} | ||||
| 	require.True(t, foundTreasury) | ||||
| 	require.True(t, foundTeam) | ||||
| 	require.True(t, foundKavadist) | ||||
| 	require.True(t, foundEcosystem) | ||||
| 
 | ||||
| } | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 Kevin Davis
						Kevin Davis