Skip to content

Commit e2607c0

Browse files
authored
Merge pull request #238 from terra-money/fix/donate-all-function
fix: donate all vesting token to work with dust delegations
2 parents 3fca4e1 + 48e314f commit e2607c0

File tree

9 files changed

+93
-7
lines changed

9 files changed

+93
-7
lines changed

.github/workflows/lint.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,4 @@ jobs:
2323
uses: golangci/golangci-lint-action@v3
2424
with:
2525
# Optional: version of golangci-lint to use in form of v1.2 or v1.2.3 or `latest` to use the latest version
26-
version: v1.49.0
26+
version: v1.51.2

.github/workflows/test-race.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,9 @@ jobs:
4848
**/**.go
4949
**/go.mod
5050
**/go.sum
51+
- name: Update deps
52+
run: go mod tidy
53+
5154
- name: Build
5255
run: GOARCH=${{ matrix.go-arch }} LEDGER_ENABLED=false make build
5356

@@ -105,6 +108,8 @@ jobs:
105108
with:
106109
name: "${{ github.sha }}-${{ matrix.part }}"
107110
if: env.GIT_DIFF
111+
- name: Update deps
112+
run: go mod tidy
108113
- name: test & coverage report creation
109114
run: |
110115
xargs --arg-file=pkgs.txt.part.${{ matrix.part }} go test -mod=readonly -timeout 30m -race -tags='cgo ledger test_ledger_mock'

.github/workflows/test.yml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@ jobs:
3535
**/**.go
3636
**/go.mod
3737
**/go.sum
38+
- name: Update deps
39+
run: go mod tidy
40+
3841
- name: Build
3942
run: GOARCH=${{ matrix.go-arch }} LEDGER_ENABLED=false make build
4043

@@ -56,6 +59,8 @@ jobs:
5659
**/**.go
5760
go.mod
5861
go.sum
62+
- name: Update deps
63+
run: go mod tidy
5964
- name: Run submodule tests and create test coverage profile.
6065
# GIT_DIFF is passed to the scripts
6166
run: bash scripts/module-tests.sh
@@ -116,6 +121,8 @@ jobs:
116121
with:
117122
name: "${{ github.sha }}-${{ matrix.part }}"
118123
if: env.GIT_DIFF
124+
- name: update deps
125+
run: go mod tidy
119126
- name: test & coverage report creation
120127
run: |
121128
cat pkgs.txt.part.${{ matrix.part }} | xargs go test -mod=readonly -timeout 30m -coverprofile=${{ matrix.part }}profile.out -covermode=atomic -tags='norace ledger test_ledger_mock'
@@ -189,6 +196,8 @@ jobs:
189196
**/**.go
190197
go.mod
191198
go.sum
199+
- name: Update deps
200+
run: go mod tidy
192201
- name: test rosetta
193202
run: |
194203
make test-rosetta
@@ -209,6 +218,8 @@ jobs:
209218
**/**.go
210219
go.mod
211220
go.sum
221+
- name: Update deps
222+
run: go mod tidy
212223
- name: start localnet
213224
run: |
214225
make clean localnet-start
@@ -250,6 +261,8 @@ jobs:
250261
**/**.go
251262
go.mod
252263
go.sum
264+
- name: Update deps
265+
run: go mod tidy
253266
- uses: actions/cache@v3
254267
with:
255268
path: ~/go/bin

.golangci.yml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,7 @@ issues:
4141
- text: "should be written without leading space as"
4242
linters:
4343
- nolintlint
44-
- path: "migrations"
45-
text: "SA1019:"
44+
- text: "SA1019:"
4645
linters:
4746
- staticcheck
4847

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -329,7 +329,7 @@ benchmark:
329329
###############################################################################
330330

331331
golangci_lint_cmd=golangci-lint
332-
golangci_version=v1.49.0
332+
golangci_version=v1.51.2
333333

334334
lint:
335335
@echo "--> Running linter"

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,7 @@ require (
161161
replace (
162162
// use cosmos fork of keyring
163163
github.com/99designs/keyring => github.com/cosmos/keyring v1.2.0
164+
github.com/ChainSafe/go-schnorrkel => github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d
164165
// dgrijalva/jwt-go is deprecated and doesn't receive security updates.
165166
// TODO: remove it: https://github.com/cosmos/cosmos-sdk/issues/13134
166167
github.com/dgrijalva/jwt-go => github.com/golang-jwt/jwt/v4 v4.4.2

x/auth/vesting/handler_test.go

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
package vesting_test
22

33
import (
4+
stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper"
45
"testing"
6+
"time"
57

68
"github.com/stretchr/testify/suite"
79
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
@@ -108,8 +110,22 @@ func (suite *HandlerTestSuite) TestMsgDonateVestingToken() {
108110
addr1 := sdk.AccAddress([]byte("addr1_______________"))
109111
addr2 := sdk.AccAddress([]byte("addr2_______________"))
110112
addr3 := sdk.AccAddress([]byte("addr3_______________"))
113+
addr4 := sdk.AccAddress([]byte("addr4_______________"))
111114

112115
valAddr := sdk.ValAddress([]byte("validator___________"))
116+
suite.app.StakingKeeper.SetValidator(ctx, stakingtypes.Validator{
117+
OperatorAddress: valAddr.String(),
118+
ConsensusPubkey: nil,
119+
Jailed: false,
120+
Status: 0,
121+
Tokens: sdk.NewInt(2),
122+
DelegatorShares: sdk.MustNewDecFromStr("1.1"),
123+
Description: stakingtypes.Description{},
124+
UnbondingHeight: 0,
125+
UnbondingTime: time.Time{},
126+
Commission: stakingtypes.Commission{},
127+
MinSelfDelegation: sdk.NewInt(1),
128+
})
113129

114130
acc1 := suite.app.AccountKeeper.NewAccountWithAddress(ctx, addr1)
115131
suite.app.AccountKeeper.SetAccount(ctx, acc1)
@@ -133,6 +149,18 @@ func (suite *HandlerTestSuite) TestMsgDonateVestingToken() {
133149
suite.app.AccountKeeper.SetAccount(ctx, acc3)
134150
suite.Require().NoError(simapp.FundAccount(suite.app.BankKeeper, ctx, addr3, balances))
135151

152+
acc4 := types.NewPermanentLockedAccount(
153+
suite.app.AccountKeeper.NewAccountWithAddress(ctx, addr4).(*authtypes.BaseAccount), balances,
154+
)
155+
acc4.DelegatedVesting = balances
156+
suite.app.AccountKeeper.SetAccount(ctx, acc4)
157+
suite.app.StakingKeeper.SetDelegation(ctx, stakingtypes.Delegation{
158+
DelegatorAddress: addr4.String(),
159+
ValidatorAddress: valAddr.String(),
160+
Shares: sdk.MustNewDecFromStr("0.1"),
161+
})
162+
suite.Require().NoError(simapp.FundAccount(suite.app.BankKeeper, ctx, addr4, balances))
163+
136164
testCases := []struct {
137165
name string
138166
msg *types.MsgDonateAllVestingTokens
@@ -153,12 +181,19 @@ func (suite *HandlerTestSuite) TestMsgDonateVestingToken() {
153181
msg: types.NewMsgDonateAllVestingTokens(addr3),
154182
expectErr: false,
155183
},
184+
{
185+
name: "donate from vesting account with dust delegation",
186+
msg: types.NewMsgDonateAllVestingTokens(addr4),
187+
expectErr: false,
188+
},
156189
}
157190

158191
for _, tc := range testCases {
159192
tc := tc
160193

161194
suite.Run(tc.name, func() {
195+
// Rollback context after every test case
196+
ctx, _ := ctx.CacheContext()
162197
res, err := suite.handler(ctx, tc.msg)
163198
if tc.expectErr {
164199
suite.Require().Error(err)
@@ -178,6 +213,9 @@ func (suite *HandlerTestSuite) TestMsgDonateVestingToken() {
178213
suite.Require().True(ok)
179214
balance := suite.app.BankKeeper.GetAllBalances(ctx, fromAddr)
180215
suite.Require().Empty(balance)
216+
217+
_, broken := stakingkeeper.DelegatorSharesInvariant(suite.app.StakingKeeper)(ctx)
218+
suite.Require().False(broken)
181219
}
182220
})
183221
}

x/auth/vesting/msg_server.go

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ package vesting
22

33
import (
44
"context"
5+
"fmt"
6+
"math"
57

68
"github.com/armon/go-metrics"
79

@@ -239,9 +241,33 @@ func (s msgServer) DonateAllVestingTokens(goCtx context.Context, msg *types.MsgD
239241
return nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "account %s not exists", msg.FromAddress)
240242
}
241243

242-
// check whether an account has any type of staking entry
243-
if len(sk.GetDelegatorDelegations(ctx, acc.GetAddress(), 1)) != 0 ||
244-
len(sk.GetUnbondingDelegations(ctx, acc.GetAddress(), 1)) != 0 ||
244+
// get all delegations of an account and undust those that have less than 1 uluna
245+
delegations := sk.GetDelegatorDelegations(ctx, acc.GetAddress(), math.MaxUint16)
246+
for _, delegation := range delegations {
247+
validatorAddr, err := sdk.ValAddressFromBech32(delegation.ValidatorAddress)
248+
if err != nil {
249+
return nil, err
250+
}
251+
validator, found := sk.GetValidator(ctx, validatorAddr)
252+
if !found {
253+
return nil, fmt.Errorf("validator not found")
254+
}
255+
// Try to delete the dust delegation
256+
_, removedTokens := sk.RemoveValidatorTokensAndShares(ctx, validator, delegation.Shares)
257+
// If the delegation is not dust, return an error and stop the donation flow
258+
if !removedTokens.IsZero() {
259+
return nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "account %s has a non-zero staking entry", msg.FromAddress)
260+
}
261+
262+
// Remove the dust delegation shares from the validator
263+
err = sk.RemoveDelegation(ctx, delegation)
264+
if err != nil {
265+
return nil, err
266+
}
267+
}
268+
269+
// check whether an account has any other type of staking entries
270+
if len(sk.GetUnbondingDelegations(ctx, acc.GetAddress(), 1)) != 0 ||
245271
len(sk.GetRedelegations(ctx, acc.GetAddress(), 1)) != 0 {
246272
return nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "account %s has staking entry", msg.FromAddress)
247273
}

x/auth/vesting/types/expected_keepers.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package types
22

33
import (
4+
"cosmossdk.io/math"
45
sdk "github.com/cosmos/cosmos-sdk/types"
56
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
67
)
@@ -23,4 +24,7 @@ type StakingKeeper interface {
2324
GetDelegatorDelegations(ctx sdk.Context, delegator sdk.AccAddress, maxRetrieve uint16) (delegations []stakingtypes.Delegation)
2425
GetUnbondingDelegations(ctx sdk.Context, delegator sdk.AccAddress, maxRetrieve uint16) (unbondingDelegations []stakingtypes.UnbondingDelegation)
2526
GetRedelegations(ctx sdk.Context, delegator sdk.AccAddress, maxRetrieve uint16) (redelegations []stakingtypes.Redelegation)
27+
RemoveValidatorTokensAndShares(ctx sdk.Context, validator stakingtypes.Validator, sharesToRemove sdk.Dec) (valOut stakingtypes.Validator, removedTokens math.Int)
28+
GetValidator(ctx sdk.Context, addr sdk.ValAddress) (validator stakingtypes.Validator, found bool)
29+
RemoveDelegation(ctx sdk.Context, delegation stakingtypes.Delegation) error
2630
}

0 commit comments

Comments
 (0)