/
gov.go
126 lines (111 loc) · 4.52 KB
/
gov.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
package keeper
import (
"fmt"
"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
govtypes "github.com/cosmos/cosmos-sdk/x/gov/types"
"github.com/ethereum/go-ethereum/common"
"github.com/functionx/fx-core/v3/x/migrate/types"
)
type GovMigrate struct {
govKey sdk.StoreKey
govKeeper types.GovKeeper
}
func NewGovMigrate(govKey sdk.StoreKey, govKeeper types.GovKeeper) MigrateI {
return &GovMigrate{
govKey: govKey,
govKeeper: govKeeper,
}
}
func (m *GovMigrate) Validate(ctx sdk.Context, _ codec.BinaryCodec, from sdk.AccAddress, to common.Address) error {
votingParams := m.govKeeper.GetVotingParams(ctx)
activeIter := m.govKeeper.ActiveProposalQueueIterator(ctx, ctx.BlockTime().Add(votingParams.VotingPeriod))
defer activeIter.Close()
for ; activeIter.Valid(); activeIter.Next() {
// check vote
proposalID, _ := govtypes.SplitActiveProposalQueueKey(activeIter.Key())
_, fromVoteFound := m.govKeeper.GetVote(ctx, proposalID, from)
_, toVoteFound := m.govKeeper.GetVote(ctx, proposalID, to.Bytes())
if fromVoteFound && toVoteFound {
return sdkerrors.Wrapf(types.ErrInvalidAddress, "can not migrate, both from and to have voting proposal %d", proposalID)
}
}
return nil
}
func (m *GovMigrate) Execute(ctx sdk.Context, cdc codec.BinaryCodec, from sdk.AccAddress, to common.Address) error {
govStore := ctx.KVStore(m.govKey)
events := make([]sdk.Event, 0, 10)
depositParams := m.govKeeper.GetDepositParams(ctx)
inactiveIter := m.govKeeper.InactiveProposalQueueIterator(ctx, ctx.BlockTime().Add(depositParams.MaxDepositPeriod))
defer inactiveIter.Close()
for ; inactiveIter.Valid(); inactiveIter.Next() {
proposalID, _ := govtypes.SplitInactiveProposalQueueKey(inactiveIter.Key())
// migrate deposit
if fromDeposit, fromFound := m.govKeeper.GetDeposit(ctx, proposalID, from); fromFound {
amount := fromDeposit.Amount
toDeposit, toFound := m.govKeeper.GetDeposit(ctx, proposalID, to.Bytes())
if toFound {
amount = amount.Add(toDeposit.Amount...)
}
events = append(events,
sdk.NewEvent(
types.EventTypeMigrateGovDeposit,
sdk.NewAttribute(types.AttributeKeyProposalId, fmt.Sprintf("%d", proposalID)),
sdk.NewAttribute(sdk.AttributeKeyAmount, fromDeposit.Amount.String()),
),
)
fromDeposit.Depositor = sdk.AccAddress(to.Bytes()).String()
fromDeposit.Amount = amount
govStore.Delete(govtypes.DepositKey(fromDeposit.ProposalId, from))
govStore.Set(govtypes.DepositKey(fromDeposit.ProposalId, to.Bytes()), cdc.MustMarshal(&fromDeposit))
}
}
votingParams := m.govKeeper.GetVotingParams(ctx)
activeIter := m.govKeeper.ActiveProposalQueueIterator(ctx, ctx.BlockTime().Add(votingParams.VotingPeriod))
defer activeIter.Close()
for ; activeIter.Valid(); activeIter.Next() {
proposalID, _ := govtypes.SplitActiveProposalQueueKey(activeIter.Key())
// migrate deposit
if fromDeposit, depositFound := m.govKeeper.GetDeposit(ctx, proposalID, from); depositFound {
amount := fromDeposit.Amount
toDeposit, toFound := m.govKeeper.GetDeposit(ctx, proposalID, to.Bytes())
if toFound {
amount = amount.Add(toDeposit.Amount...)
}
events = append(events,
sdk.NewEvent(
types.EventTypeMigrateGovDeposit,
sdk.NewAttribute(types.AttributeKeyProposalId, fmt.Sprintf("%d", proposalID)),
sdk.NewAttribute(sdk.AttributeKeyAmount, fromDeposit.Amount.String()),
),
)
fromDeposit.Depositor = sdk.AccAddress(to.Bytes()).String()
fromDeposit.Amount = amount
govStore.Delete(govtypes.DepositKey(proposalID, from))
govStore.Set(govtypes.DepositKey(proposalID, to.Bytes()), cdc.MustMarshal(&fromDeposit))
}
// migrate vote
if fromVote, voteFound := m.govKeeper.GetVote(ctx, proposalID, from); voteFound {
_, toFound := m.govKeeper.GetVote(ctx, proposalID, to.Bytes())
if toFound {
return sdkerrors.Wrapf(types.ErrInvalidAddress, "can not migrate, both from and to have voting proposal %d", proposalID)
}
fromVote.Voter = sdk.AccAddress(to.Bytes()).String()
govStore.Delete(govtypes.VoteKey(proposalID, from))
govStore.Set(govtypes.VoteKey(proposalID, to.Bytes()), cdc.MustMarshal(&fromVote))
// add events
events = append(events,
sdk.NewEvent(
types.EventTypeMigrateGovVote,
sdk.NewAttribute(types.AttributeKeyProposalId, fmt.Sprintf("%d", proposalID)),
sdk.NewAttribute(types.AttributeKeyVoteOption, fromVote.Option.String()), // nolint:staticcheck
),
)
}
}
if len(events) > 0 {
ctx.EventManager().EmitEvents(events)
}
return nil
}