mirror of
				https://github.com/0glabs/0g-chain.git
				synced 2025-10-31 23:17:27 +00:00 
			
		
		
		
	update lend proposals to use community pool (#1460)
* point community pool lend proposals at fee pool * update community pool lend proposal tests * remove unused begin blocker * increase test coverage * fix x/community proposal comments
This commit is contained in:
		
							parent
							
								
									b26e12a579
								
							
						
					
					
						commit
						d05484cf88
					
				| @ -1,12 +0,0 @@ | |||||||
| package community |  | ||||||
| 
 |  | ||||||
| import ( |  | ||||||
| 	sdk "github.com/cosmos/cosmos-sdk/types" |  | ||||||
| 	"github.com/kava-labs/kava/x/community/keeper" |  | ||||||
| 	abci "github.com/tendermint/tendermint/abci/types" |  | ||||||
| ) |  | ||||||
| 
 |  | ||||||
| // BeginBlocker runs at the start of every block.
 |  | ||||||
| func BeginBlocker(ctx sdk.Context, _ abci.RequestBeginBlock, k keeper.Keeper) { |  | ||||||
| 	// TODO: process proposals here
 |  | ||||||
| } |  | ||||||
| @ -61,3 +61,26 @@ func TestParseWithdrawProposal(t *testing.T) { | |||||||
| 	require.Equal(t, "Withdraw some KAVA from community pool to Lend!", proposal.Description) | 	require.Equal(t, "Withdraw some KAVA from community pool to Lend!", proposal.Description) | ||||||
| 	require.Equal(t, expectedAmount, proposal.Amount) | 	require.Equal(t, expectedAmount, proposal.Amount) | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | func TestParseFileNoExists(t *testing.T) { | ||||||
|  | 	cdc := codec.NewAminoCodec(codec.NewLegacyAmino()) | ||||||
|  | 	_, err := utils.ParseCommunityPoolLendDepositProposal(cdc, "not-a-file.json") | ||||||
|  | 	require.ErrorContains(t, err, "no such file or directory") | ||||||
|  | 	_, err = utils.ParseCommunityPoolLendWithdrawProposal(cdc, "not-a-file.json") | ||||||
|  | 	require.ErrorContains(t, err, "no such file or directory") | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func TestParseFileMalformed(t *testing.T) { | ||||||
|  | 	cdc := codec.NewAminoCodec(codec.NewLegacyAmino()) | ||||||
|  | 	malformed := testutil.WriteToNewTempFile(t, ` | ||||||
|  | { | ||||||
|  | 	"title": "I'm malformed b/c there's no closing quote, | ||||||
|  | 	"description": "A description", | ||||||
|  | 	"amount": [{"denom": "ukava", "amount": "100000000000"}] | ||||||
|  | } | ||||||
|  | `) | ||||||
|  | 	_, err := utils.ParseCommunityPoolLendDepositProposal(cdc, malformed.Name()) | ||||||
|  | 	require.ErrorContains(t, err, "invalid character") | ||||||
|  | 	_, err = utils.ParseCommunityPoolLendWithdrawProposal(cdc, malformed.Name()) | ||||||
|  | 	require.ErrorContains(t, err, "invalid character") | ||||||
|  | } | ||||||
|  | |||||||
| @ -12,8 +12,6 @@ import ( | |||||||
| 	"github.com/kava-labs/kava/x/community/types" | 	"github.com/kava-labs/kava/x/community/types" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| const legacyCommunityPoolAddr = "kava1jv65s3grqf6v6jl3dp4t6c9t9rk99cd8m2splc" |  | ||||||
| 
 |  | ||||||
| type grpcQueryTestSuite struct { | type grpcQueryTestSuite struct { | ||||||
| 	KeeperTestSuite | 	KeeperTestSuite | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -8,10 +8,31 @@ import ( | |||||||
| 
 | 
 | ||||||
| // HandleCommunityPoolLendDepositProposal is a handler for executing a passed community pool lend deposit proposal.
 | // HandleCommunityPoolLendDepositProposal is a handler for executing a passed community pool lend deposit proposal.
 | ||||||
| func HandleCommunityPoolLendDepositProposal(ctx sdk.Context, k Keeper, p *types.CommunityPoolLendDepositProposal) error { | func HandleCommunityPoolLendDepositProposal(ctx sdk.Context, k Keeper, p *types.CommunityPoolLendDepositProposal) error { | ||||||
|  | 	// move funds from community pool to x/community so hard position is held by this module.
 | ||||||
|  | 	err := k.distrKeeper.DistributeFromFeePool(ctx, p.Amount, k.moduleAddress) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 	// deposit funds into hard
 | ||||||
| 	return k.hardKeeper.Deposit(ctx, k.moduleAddress, p.Amount) | 	return k.hardKeeper.Deposit(ctx, k.moduleAddress, p.Amount) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // HandleCommunityPoolLendWithdrawProposal is a handler for executing a passed community pool lend withdraw proposal.
 | // HandleCommunityPoolLendWithdrawProposal is a handler for executing a passed community pool lend withdraw proposal.
 | ||||||
| func HandleCommunityPoolLendWithdrawProposal(ctx sdk.Context, k Keeper, p *types.CommunityPoolLendWithdrawProposal) error { | func HandleCommunityPoolLendWithdrawProposal(ctx sdk.Context, k Keeper, p *types.CommunityPoolLendWithdrawProposal) error { | ||||||
| 	return k.hardKeeper.Withdraw(ctx, k.moduleAddress, p.Amount) | 	// hard allows attempting to withdraw more funds than there is a deposit for.
 | ||||||
|  | 	// this means the amount that gets withdrawn will not necessarily match the amount set in the proposal.
 | ||||||
|  | 	// to calculate how much is withdrawn, compare this module's balance before & after withdraw.
 | ||||||
|  | 	balanceBefore := k.bankKeeper.GetAllBalances(ctx, k.moduleAddress) | ||||||
|  | 
 | ||||||
|  | 	// withdraw funds from x/hard to this module account
 | ||||||
|  | 	err := k.hardKeeper.Withdraw(ctx, k.moduleAddress, p.Amount) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	balanceAfter := k.bankKeeper.GetAllBalances(ctx, k.moduleAddress) | ||||||
|  | 	totalWithdrawn := balanceAfter.Sub(balanceBefore) | ||||||
|  | 
 | ||||||
|  | 	// send all withdrawn coins back to community pool
 | ||||||
|  | 	return k.distrKeeper.FundCommunityPool(ctx, totalWithdrawn, k.moduleAddress) | ||||||
| } | } | ||||||
|  | |||||||
| @ -78,16 +78,11 @@ func (suite *proposalTestSuite) SetupTest() { | |||||||
| 
 | 
 | ||||||
| 	// give the community pool some funds
 | 	// give the community pool some funds
 | ||||||
| 	// ukava
 | 	// ukava
 | ||||||
| 	err := suite.App.FundModuleAccount(suite.Ctx, types.ModuleAccountName, ukava(1e10)) | 	suite.FundCommunityPool(ukava(1e10)) | ||||||
| 	suite.NoError(err) |  | ||||||
| 
 |  | ||||||
| 	// usdx
 | 	// usdx
 | ||||||
| 	err = suite.App.FundModuleAccount(suite.Ctx, types.ModuleAccountName, usdx(1e10)) | 	suite.FundCommunityPool(usdx(1e10)) | ||||||
| 	suite.NoError(err) |  | ||||||
| 
 |  | ||||||
| 	// other-denom
 | 	// other-denom
 | ||||||
| 	err = suite.App.FundModuleAccount(suite.Ctx, types.ModuleAccountName, otherdenom(1e10)) | 	suite.FundCommunityPool(otherdenom(1e10)) | ||||||
| 	suite.NoError(err) |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (suite *proposalTestSuite) NextBlock() { | func (suite *proposalTestSuite) NextBlock() { | ||||||
| @ -99,6 +94,27 @@ func (suite *proposalTestSuite) NextBlock() { | |||||||
| 	suite.App.BeginBlocker(suite.Ctx, abcitypes.RequestBeginBlock{}) | 	suite.App.BeginBlocker(suite.Ctx, abcitypes.RequestBeginBlock{}) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | func (suite *proposalTestSuite) FundCommunityPool(coins sdk.Coins) { | ||||||
|  | 	// mint to ephemeral account
 | ||||||
|  | 	ephemeralAcc := app.RandomAddress() | ||||||
|  | 	suite.NoError(suite.App.FundAccount(suite.Ctx, ephemeralAcc, coins)) | ||||||
|  | 	// fund community pool with newly minted coins
 | ||||||
|  | 	suite.NoError(suite.App.GetDistrKeeper().FundCommunityPool(suite.Ctx, coins, ephemeralAcc)) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (suite *proposalTestSuite) GetCommunityPoolBalance() sdk.Coins { | ||||||
|  | 	balance, change := suite.App.GetDistrKeeper().GetFeePoolCommunityCoins(suite.Ctx).TruncateDecimal() | ||||||
|  | 	// expect no decimal dust
 | ||||||
|  | 	suite.True(sdk.NewDecCoins().IsEqual(change), "expected no decimal dust in community pool") | ||||||
|  | 	return balance | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (suite *proposalTestSuite) CheckCommunityPoolBalance(expected sdk.Coins) { | ||||||
|  | 	actual := suite.GetCommunityPoolBalance() | ||||||
|  | 	// check that balance is expected
 | ||||||
|  | 	suite.True(expected.IsEqual(actual), fmt.Sprintf("unexpected balance in community pool\nexpected: %s\nactual: %s", expected, actual)) | ||||||
|  | } | ||||||
|  | 
 | ||||||
| func (suite *proposalTestSuite) TestCommunityLendDepositProposal() { | func (suite *proposalTestSuite) TestCommunityLendDepositProposal() { | ||||||
| 	testCases := []struct { | 	testCases := []struct { | ||||||
| 		name             string | 		name             string | ||||||
| @ -148,7 +164,7 @@ func (suite *proposalTestSuite) TestCommunityLendDepositProposal() { | |||||||
| 					Amount:      ukava(1e11), | 					Amount:      ukava(1e11), | ||||||
| 				}, | 				}, | ||||||
| 			}, | 			}, | ||||||
| 			expectedErr:      "insufficient funds", | 			expectedErr:      "community pool does not have sufficient coins to distribute", | ||||||
| 			expectedDeposits: []sdk.Coins{}, | 			expectedDeposits: []sdk.Coins{}, | ||||||
| 		}, | 		}, | ||||||
| 		{ | 		{ | ||||||
| @ -280,7 +296,7 @@ func (suite *proposalTestSuite) TestCommunityLendWithdrawProposal() { | |||||||
| 				suite.NoError(err, "unexpected error while seeding lend deposit") | 				suite.NoError(err, "unexpected error while seeding lend deposit") | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			beforeBalance := suite.Keeper.GetModuleAccountBalance(suite.Ctx) | 			beforeBalance := suite.GetCommunityPoolBalance() | ||||||
| 
 | 
 | ||||||
| 			// run the proposals
 | 			// run the proposals
 | ||||||
| 			for i, proposal := range tc.proposals { | 			for i, proposal := range tc.proposals { | ||||||
| @ -306,7 +322,7 @@ func (suite *proposalTestSuite) TestCommunityLendWithdrawProposal() { | |||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			// expect funds to be distributed back to community pool
 | 			// expect funds to be distributed back to community pool
 | ||||||
| 			suite.App.CheckBalance(suite.T(), suite.Ctx, suite.MaccAddress, beforeBalance.Add(tc.expectedWithdrawal...)) | 			suite.CheckCommunityPoolBalance(beforeBalance.Add(tc.expectedWithdrawal...)) | ||||||
| 		}) | 		}) | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  | |||||||
| @ -27,5 +27,6 @@ type HardKeeper interface { | |||||||
| 
 | 
 | ||||||
| // DistributionKeeper defines the contract needed to be fulfilled for distribution dependencies.
 | // DistributionKeeper defines the contract needed to be fulfilled for distribution dependencies.
 | ||||||
| type DistributionKeeper interface { | type DistributionKeeper interface { | ||||||
| 	GetFeePoolCommunityCoins(ctx sdk.Context) sdk.DecCoins | 	DistributeFromFeePool(ctx sdk.Context, amount sdk.Coins, receiveAddr sdk.AccAddress) error | ||||||
|  | 	FundCommunityPool(ctx sdk.Context, amount sdk.Coins, sender sdk.AccAddress) error | ||||||
| } | } | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 Robert Pirtle
						Robert Pirtle