@@ -18,19 +18,28 @@ package upgrade
1818
1919import (
2020 "context"
21+ "fmt"
22+ "sort"
2123
24+ "cosmossdk.io/core/address"
2225 "cosmossdk.io/log"
26+ "cosmossdk.io/math"
2327 upgradetypes "cosmossdk.io/x/upgrade/types"
28+ dollarkeeper "dollar.noble.xyz/v2/keeper"
29+ vaultstypes "dollar.noble.xyz/v2/types/vaults"
2430 sdk "github.com/cosmos/cosmos-sdk/types"
2531 "github.com/cosmos/cosmos-sdk/types/module"
2632 clientkeeper "github.com/cosmos/ibc-go/v8/modules/core/02-client/keeper"
33+ authoritytypes "github.com/noble-assets/authority/types"
2734)
2835
2936func CreateUpgradeHandler (
3037 mm * module.Manager ,
3138 cfg module.Configurator ,
3239 logger log.Logger ,
40+ addressCdc address.Codec ,
3341 clientKeeper clientkeeper.Keeper ,
42+ dollarKeeper * dollarkeeper.Keeper ,
3443) upgradetypes.UpgradeHandler {
3544 return func (ctx context.Context , _ upgradetypes.Plan , vm module.VersionMap ) (module.VersionMap , error ) {
3645 vm , err := mm .RunMigrations (ctx , cfg , vm )
@@ -52,6 +61,82 @@ func CreateUpgradeHandler(
5261 }
5362 }
5463
64+ vaultServer := dollarkeeper .NewVaultsMsgServer (dollarKeeper )
65+
66+ // Unlock all user positions from the Staked Vault.
67+ if err = endVaultsSeasonTwo (ctx , logger , addressCdc , dollarKeeper , vaultServer ); err != nil {
68+ return vm , err
69+ }
70+
71+ // Pause all Vaults permanently.
72+ if _ , err = vaultServer .SetPausedState (ctx , & vaultstypes.MsgSetPausedState {
73+ Signer : authoritytypes .ModuleAddress .String (),
74+ Paused : vaultstypes .ALL ,
75+ }); err != nil {
76+ return vm , err
77+ }
78+
5579 return vm , nil
5680 }
5781}
82+
83+ // endVaultsSeasonTwo handles the logic to end Vaults Season Two, unlocking all
84+ // Staked vault user positions.
85+ func endVaultsSeasonTwo (
86+ ctx context.Context ,
87+ logger log.Logger ,
88+ addressCdc address.Codec ,
89+ k * dollarkeeper.Keeper ,
90+ vaultServer vaultstypes.MsgServer ,
91+ ) error {
92+ // Get all the vaults positions.
93+ positions , err := k .GetVaultsPositions (ctx )
94+ if err != nil {
95+ return err
96+ }
97+
98+ // Create a mapping by address and the total positions amount.
99+ stakedUsers := map [string ]math.Int {}
100+ var stakedUsersAddress []string
101+
102+ // Iterate through all the positions.
103+ logger .Info ("collecting vault positions" )
104+ for _ , position := range positions {
105+ switch position .Vault {
106+ case vaultstypes .STAKED :
107+ addr , err := addressCdc .BytesToString (position .Address )
108+ if err != nil {
109+ logger .Warn ("invalid position address: " + err .Error ())
110+ continue
111+ }
112+
113+ if _ , exists := stakedUsers [addr ]; ! exists {
114+ stakedUsers [addr ] = position .Amount
115+ stakedUsersAddress = append (stakedUsersAddress , addr )
116+ } else {
117+ stakedUsers [addr ] = stakedUsers [addr ].Add (position .Amount )
118+ }
119+ }
120+ }
121+
122+ sort .Strings (stakedUsersAddress )
123+
124+ // Unlock all the Staked vault positions.
125+ logger .Info (fmt .Sprintf ("unlocking %d staked vault positions" , len (stakedUsers )))
126+ stakedUsersProcessed := 0
127+ for _ , stakedUserAddr := range stakedUsersAddress {
128+ stakedUserTotalAmount := stakedUsers [stakedUserAddr ]
129+ if _ , unlockErr := vaultServer .Unlock (ctx , & vaultstypes.MsgUnlock {
130+ Signer : stakedUserAddr ,
131+ Vault : vaultstypes .STAKED ,
132+ Amount : stakedUserTotalAmount ,
133+ }); unlockErr != nil {
134+ logger .Error (fmt .Sprintf ("failed to unlock staked vault position for %s: %v" , stakedUserAddr , err ))
135+ continue
136+ }
137+ stakedUsersProcessed += 1
138+ }
139+ logger .Info (fmt .Sprintf ("unlocked %d/%d staked vault positions successfully" , stakedUsersProcessed , len (stakedUsers )))
140+
141+ return nil
142+ }
0 commit comments