From a23ecf8e3a975b98cd154479a4e2c0314da3009b Mon Sep 17 00:00:00 2001 From: sampocs Date: Tue, 28 Jan 2025 13:48:29 -0600 Subject: [PATCH] stTIA Migration (#1271) Co-authored-by: Assaf Morami --- app/app.go | 2 + app/upgrades.go | 14 + app/upgrades/v24/upgrades.go | 2 +- app/upgrades/v25/upgrades.go | 65 + app/upgrades/v25/upgrades_test.go | 25 + app/upgrades/v25/validators.go | 93 + proto/stride/staketia/staketia.proto | 41 +- proto/stride/staketia/tx.proto | 7 + scripts/version.sh | 8 +- x/stakeibc/keeper/msg_server_test.go | 2 +- x/stakeibc/keeper/validator.go | 15 +- x/staketia/client/cli/tx.go | 49 +- x/staketia/keeper/abci.go | 11 +- x/staketia/keeper/delegation.go | 112 +- x/staketia/keeper/delegation_test.go | 301 +-- x/staketia/keeper/events.go | 1 - x/staketia/keeper/hooks.go | 26 - x/staketia/keeper/host_zone_test.go | 31 +- x/staketia/keeper/invariants.go | 2 +- x/staketia/keeper/keeper.go | 6 + x/staketia/keeper/migration.go | 267 ++ x/staketia/keeper/migration_test.go | 200 ++ x/staketia/keeper/msg_server.go | 96 +- x/staketia/keeper/msg_server_test.go | 227 +- x/staketia/keeper/redemption_rate.go | 116 +- x/staketia/keeper/redemption_rate_test.go | 169 +- x/staketia/keeper/unbonding.go | 159 +- x/staketia/keeper/unbonding_test.go | 400 +-- x/staketia/legacytypes/staketia.pb.go | 2739 +++++++++++++++++++++ x/staketia/types/celestia.go | 8 +- x/staketia/types/errors.go | 1 + x/staketia/types/expected_keepers.go | 19 + x/staketia/types/genesis.go | 11 +- x/staketia/types/host_zone.go | 40 - x/staketia/types/host_zone_test.go | 133 - x/staketia/types/msgs.go | 7 +- x/staketia/types/msgs_test.go | 16 +- x/staketia/types/staketia.pb.go | 441 +--- x/staketia/types/tx.pb.go | 230 +- 39 files changed, 4140 insertions(+), 1952 deletions(-) create mode 100644 app/upgrades/v25/upgrades.go create mode 100644 app/upgrades/v25/upgrades_test.go create mode 100644 app/upgrades/v25/validators.go create mode 100644 x/staketia/keeper/migration.go create mode 100644 x/staketia/keeper/migration_test.go create mode 100644 x/staketia/legacytypes/staketia.pb.go diff --git a/app/app.go b/app/app.go index 721c889d7a..cc14687429 100644 --- a/app/app.go +++ b/app/app.go @@ -736,6 +736,8 @@ func NewStrideApp( app.BankKeeper, app.ICAOracleKeeper, app.RatelimitKeeper, + app.RecordsKeeper, + app.StakeibcKeeper, app.TransferKeeper, ) stakeTiaModule := staketia.NewAppModule(appCodec, app.StaketiaKeeper) diff --git a/app/upgrades.go b/app/upgrades.go index fbcc5f36fa..90814b1f77 100644 --- a/app/upgrades.go +++ b/app/upgrades.go @@ -34,6 +34,7 @@ import ( v22 "github.com/Stride-Labs/stride/v24/app/upgrades/v22" v23 "github.com/Stride-Labs/stride/v24/app/upgrades/v23" v24 "github.com/Stride-Labs/stride/v24/app/upgrades/v24" + v25 "github.com/Stride-Labs/stride/v24/app/upgrades/v25" v3 "github.com/Stride-Labs/stride/v24/app/upgrades/v3" v4 "github.com/Stride-Labs/stride/v24/app/upgrades/v4" v5 "github.com/Stride-Labs/stride/v24/app/upgrades/v5" @@ -324,6 +325,19 @@ func (app *StrideApp) setupUpgradeHandlers(appOpts servertypes.AppOptions) { ), ) + // v25 upgrade handler + app.UpgradeKeeper.SetUpgradeHandler( + v25.UpgradeName, + v25.CreateUpgradeHandler( + app.mm, + app.configurator, + app.BankKeeper, + app.RecordsKeeper, + app.StakeibcKeeper, + app.StaketiaKeeper, + ), + ) + upgradeInfo, err := app.UpgradeKeeper.ReadUpgradeInfoFromDisk() if err != nil { panic(fmt.Errorf("Failed to read upgrade info from disk: %w", err)) diff --git a/app/upgrades/v24/upgrades.go b/app/upgrades/v24/upgrades.go index 85c5304712..bbcba1f502 100644 --- a/app/upgrades/v24/upgrades.go +++ b/app/upgrades/v24/upgrades.go @@ -25,7 +25,7 @@ var ( OsmosisRedemptionRateBuffer = sdk.MustNewDecFromStr("0.02") ) -// CreateUpgradeHandler creates an SDK upgrade handler for v23 +// CreateUpgradeHandler creates an SDK upgrade handler for v24 func CreateUpgradeHandler( mm *module.Manager, configurator module.Configurator, diff --git a/app/upgrades/v25/upgrades.go b/app/upgrades/v25/upgrades.go new file mode 100644 index 0000000000..83689ef6da --- /dev/null +++ b/app/upgrades/v25/upgrades.go @@ -0,0 +1,65 @@ +package v25 + +import ( + errorsmod "cosmossdk.io/errors" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/module" + bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper" + upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types" + + recordskeeper "github.com/Stride-Labs/stride/v24/x/records/keeper" + stakeibckeeper "github.com/Stride-Labs/stride/v24/x/stakeibc/keeper" + stakeibctypes "github.com/Stride-Labs/stride/v24/x/stakeibc/types" + staketiakeeper "github.com/Stride-Labs/stride/v24/x/staketia/keeper" + staketiatypes "github.com/Stride-Labs/stride/v24/x/staketia/types" +) + +const UpgradeName = "v25" + +// CreateUpgradeHandler creates an SDK upgrade handler for v25 +func CreateUpgradeHandler( + mm *module.Manager, + configurator module.Configurator, + bankKeeper bankkeeper.Keeper, + recordsKeeper recordskeeper.Keeper, + stakeibcKeeper stakeibckeeper.Keeper, + staketiaKeeper staketiakeeper.Keeper, +) upgradetypes.UpgradeHandler { + return func(ctx sdk.Context, _ upgradetypes.Plan, vm module.VersionMap) (module.VersionMap, error) { + ctx.Logger().Info("Starting upgrade v25...") + + // Migrate staketia to stakeibc + if err := staketiakeeper.InitiateMigration(ctx, staketiaKeeper, bankKeeper, recordsKeeper, stakeibcKeeper); err != nil { + return vm, errorsmod.Wrapf(err, "unable to migrate staketia to stakeibc") + } + + // Add celestia validators + if err := AddCelestiaValidators(ctx, stakeibcKeeper); err != nil { + return vm, errorsmod.Wrapf(err, "unable to add celestia validators") + } + + ctx.Logger().Info("Running module migrations...") + return mm.RunMigrations(ctx, configurator, vm) + } +} + +// Adds the full celestia validator set, with a 0 delegation for each +func AddCelestiaValidators(ctx sdk.Context, k stakeibckeeper.Keeper) error { + for _, validatorConfig := range Validators { + validator := stakeibctypes.Validator{ + Name: validatorConfig.name, + Address: validatorConfig.address, + Weight: validatorConfig.weight, + } + + if err := k.AddValidatorToHostZone(ctx, staketiatypes.CelestiaChainId, validator, false); err != nil { + return err + } + + // Query and store the validator's sharesToTokens rate + if err := k.QueryValidatorSharesToTokensRate(ctx, staketiatypes.CelestiaChainId, validatorConfig.address); err != nil { + return err + } + } + return nil +} diff --git a/app/upgrades/v25/upgrades_test.go b/app/upgrades/v25/upgrades_test.go new file mode 100644 index 0000000000..956dfa79ed --- /dev/null +++ b/app/upgrades/v25/upgrades_test.go @@ -0,0 +1,25 @@ +package v25_test + +import ( + "testing" + + "github.com/stretchr/testify/suite" + + "github.com/Stride-Labs/stride/v24/app/apptesting" +) + +type UpgradeTestSuite struct { + apptesting.AppTestHelper +} + +func (s *UpgradeTestSuite) SetupTest() { + s.Setup() +} + +func TestKeeperTestSuite(t *testing.T) { + suite.Run(t, new(UpgradeTestSuite)) +} + +func (s *UpgradeTestSuite) TestUpgrade() { + +} diff --git a/app/upgrades/v25/validators.go b/app/upgrades/v25/validators.go new file mode 100644 index 0000000000..5350df45c5 --- /dev/null +++ b/app/upgrades/v25/validators.go @@ -0,0 +1,93 @@ +package v25 + +var Validators = []struct { + address string + name string + weight uint64 +}{ + {address: "celestiavaloper1uvytvhunccudw8fzaxvsrumec53nawyj939gj9", name: "go", weight: 954}, + {address: "celestiavaloper1e2p4u5vqwgum7pm9vhp0yjvl58gvhfc6yfatw4", name: "finoaconsensusservices", weight: 935}, + {address: "celestiavaloper15urq2dtp9qce4fyc85m6upwm9xul3049gwdz0x", name: "chorusone", weight: 806}, + {address: "celestiavaloper1r4kqtye4dzacmrwnh6f057p50pdjm8g59tlhhg", name: "p2porg", weight: 643}, + {address: "celestiavaloper1jkuw8rxxrsgn9pq009987kzelkp46cgcaa7lhj", name: "cuck", weight: 519}, + {address: "celestiavaloper1xqc7w3pe38kg4tswjt7mnvks7gy4p38vtsuycj", name: "figment", weight: 344}, + {address: "celestiavaloper1ac4mnwg79gyvd0x5trl2fgjv07lgfas02jf378", name: "p-opsteam", weight: 334}, + {address: "celestiavaloper1uqj5ul7jtpskk9ste9mfv6jvh0y3w34vtpz3gw", name: "cosmostation", weight: 303}, + {address: "celestiavaloper1mhux0vt6qszz8qwv8axggt02jjm7tuvdfhz78j", name: "twinstake", weight: 294}, + {address: "celestiavaloper1uwmf03ke52vld2sa9khs0nslpgzwsm5xs5e4pn", name: "keplr", weight: 253}, + {address: "celestiavaloper1r5xt7twqmh39ky72f4txxjrhlt2z0qwwmdal8c", name: "imperator", weight: 242}, + {address: "celestiavaloper1hm2d8e6nd5ngtlte3hlded03vgj3rer94vmdml", name: "nodesguru", weight: 219}, + {address: "celestiavaloper1v5hrqlv8dqgzvy0pwzqzg0gxy899rm4klzxm07", name: "ai", weight: 207}, + {address: "celestiavaloper1jgqewpzn7dww5tlpnkypm72fm8tjznmw7ll7ls", name: "polkachu", weight: 195}, + {address: "celestiavaloper15kpw453rgqrranltr8pcy9muryf3jjd7esw38j", name: "binarybuilders", weight: 193}, + {address: "celestiavaloper1463wx5xkus5hyugyecvlhv9qpxklz62kyhwcts", name: "galaxydigital", weight: 184}, + {address: "celestiavaloper133t4gpv4vhpqgfn9gr8l4u423zrglg8rkqeupr", name: "upnode|0%fee", weight: 182}, + {address: "celestiavaloper1j2jq259d3rrc24876gwxg0ksp0lhd8gy49k6st", name: "qubelabs", weight: 180}, + {address: "celestiavaloper1wu24jxpn9j0580ehjz344d58cf3t7lzrrgqmnr", name: "stakingfacilities", weight: 170}, + {address: "celestiavaloper1nwu3ugynh8m6r7aphv0uxnca84t7gnruvyye9c", name: "xprv", weight: 166}, + {address: "celestiavaloper1ftmw4wh8dq2ljw0xq3xgg00dl7l20se3lrml7q", name: "hextechnologies", weight: 165}, + {address: "celestiavaloper1murrqgqahxevedty0nzqrn5hj434fvffxufxcl", name: "01node", weight: 165}, + {address: "celestiavaloper1amxp3ah9anq4pmpnsknls7sql3kras9hs8pu0g", name: "iykyk", weight: 162}, + {address: "celestiavaloper187avawwq7qhanrkxf45mayztdqsr49hu8lezdh", name: "zkv", weight: 144}, + {address: "celestiavaloper1zqjpfxtv3yp6kdlgra4hc9zehxgvpaw82hxr5w", name: "nocturnallabs", weight: 138}, + {address: "celestiavaloper1c9ye54e3pzwm3e0zpdlel6pnavrj9qqvjeqh0m", name: "nansen", weight: 105}, + {address: "celestiavaloper1qe8uuf5x69c526h4nzxwv4ltftr73v7q5qhs58", name: "stakecito", weight: 98}, + {address: "celestiavaloper19v94c3z7ckarwsum76kaagma0wqsqhh5nl5zqg", name: "validatus", weight: 98}, + {address: "celestiavaloper1demcj83q7nxt6gtqxlu7qsmwqpt4jspj3alr92", name: "mzonder", weight: 87}, + {address: "celestiavaloper1knn88yl08ctsdrtxvfp39jywt7rph9ptv7532y", name: "blackblocks", weight: 83}, + {address: "celestiavaloper1pmn4cjwf26hkcpvyl322glhpdpcemcel8ca2vl", name: "staked", weight: 67}, + {address: "celestiavaloper1zdrz4w2pwwffdvmpum0626vycel9caay9n3pll", name: "w3hitchhiker", weight: 52}, + {address: "celestiavaloper19f0w9svr905fhefusyx4z8sf83j6et0g57nch8", name: "nodestake", weight: 50}, + {address: "celestiavaloper140l6y2gp3gxvay6qtn70re7z2s0gn57zcvqd22", name: "lavenderfivenodes", weight: 47}, + {address: "celestiavaloper1rcm7tth05klgkqpucdhm5hexnk49dfda3l3hak", name: "allnodes", weight: 47}, + {address: "celestiavaloper1v987evnk7hsqct7smdqpxqprhvlcxgt43kyewc", name: "alphab", weight: 46}, + {address: "celestiavaloper14v4ush42xewyeuuldf6jtdz0a7pxg5fwrlumwf", name: "latamnodes", weight: 43}, + {address: "celestiavaloper1m58punvt32u07ra4p6x7krgxakye3m90rzgm4c", name: "nodeguardians", weight: 41}, + {address: "celestiavaloper107lwx458gy345ag2afx9a7e2kkl7x49y3433gj", name: "enigma", weight: 40}, + {address: "celestiavaloper1pnzrk7yzx0nr9xrcjyswj7ram4qxlrfz28xvn6", name: "nakoturk", weight: 39}, + {address: "celestiavaloper17p8y0sm76zhrtjny98tknevafvlq9860ehykz3", name: "kjnodes", weight: 39}, + {address: "celestiavaloper1un77nfm6axkhkupe8fk4xl6fd4adz3y59fucpu", name: "easy2stake", weight: 35}, + {address: "celestiavaloper1593ns00rftlqp2gyu6wdmrqpgv5frv0hsf4sw2", name: "forbole", weight: 33}, + {address: "celestiavaloper1djqecw6nn5tydxq0shan7srv8j65clsfmnxcfu", name: "kiln", weight: 33}, + {address: "celestiavaloper14ntfv0qkg8522xe0pvrfgqxcmnj5x466v8z3tl", name: "b-harvest", weight: 32}, + {address: "celestiavaloper19y52qzj4hxw0u68krfptkjlm77cvth8dgum7yu", name: "brightlystake", weight: 31}, + {address: "celestiavaloper1dlsl4u42ycahzjfwc6td6upgsup9tt7cz8vqm4", name: "stakin", weight: 30}, + {address: "celestiavaloper1eualhqh07w7p45g45hvrjagkcxsfnflzdw5jzg", name: "everstake", weight: 29}, + {address: "celestiavaloper1ej2es5fjztqjcd4pwa0zyvaevtjd2y5wh8xeg4", name: "frens", weight: 28}, + {address: "celestiavaloper1yknsyf9ws4ugtv3r9g43kwqkne4zmrupcxhlth", name: "stakelyio", weight: 27}, + {address: "celestiavaloper1vje2he3pcq3w5udyvla7zm9qd5yes6hzffsjxj", name: "dsrv", weight: 26}, + {address: "celestiavaloper1auqmdc2pnx5gxvakjdsc9v9zc4y2ga0hcaxg9x", name: "projectblanc", weight: 25}, + {address: "celestiavaloper1ryyzale2qcp3e35k0ze3kc0mpfdtw9jagcss3k", name: "larryengineer", weight: 24}, + {address: "celestiavaloper1lqfqp2w65pjsu6hg3qg4qfp4t2t6da4a3gg8ad", name: "stakelab", weight: 24}, + {address: "celestiavaloper1u4vhh70lwlt2va7hw5evzl6sap92t0m9nqzmud", name: "swissstaking", weight: 22}, + {address: "celestiavaloper17h2x3j7u44qkrq0sk8ul0r2qr440rwgj8g0ng0", name: "freshstaking", weight: 22}, + {address: "celestiavaloper1vdp8q3v72mntewqqak56yk3gzz7h5ukmeym9hk", name: "stakingcabin", weight: 22}, + {address: "celestiavaloper17srrapx2cvqyyy4rg3menq0hn86py8f3klelhl", name: "contributiondao", weight: 21}, + {address: "celestiavaloper1vl3dkus7g0cj4lg0e2jrqk2reukmlht0ee7cr4", name: "bwarelabs", weight: 20}, + {address: "celestiavaloper12t63cy8kn5n7qw77xvjn00ymcr0uuvz2vh8p79", name: "lemniscap", weight: 18}, + {address: "celestiavaloper1njzuxja7aa7w2d69ldg2r8c6qhjzfcd42huq0x", name: "kek", weight: 17}, + {address: "celestiavaloper19kr4f4ndyek6kwa0vt3w4un8he0tkekufa8t2g", name: "staking4all", weight: 17}, + {address: "celestiavaloper1pavac9yrlgwyw6v9yx84sttc96n9ee9zrja2u7", name: "gunter", weight: 17}, + {address: "celestiavaloper1cs37tvmahavw8xcnzcgyz342sh0al37ma4zqat", name: "cumulo", weight: 17}, + {address: "celestiavaloper138jl42zlxue4wpvnugcdqhxjmyd2vpt6qhs5ls", name: "cryptocrewvalidators", weight: 16}, + {address: "celestiavaloper125xazqstxpav7ekrt4w8km7ccdu8ytj40xug70", name: "validatrium", weight: 16}, + {address: "celestiavaloper1slnzmhg3kwhc2c5y9atrt5jtmt3sauzzp4tguj", name: "bitnordic", weight: 16}, + {address: "celestiavaloper1qx43f066sh6728avms4qq09cj2a3mg83dgjh22", name: "unbonding-pleaseredelegate", weight: 16}, + {address: "celestiavaloper1qxeza0sa037u35p3ze8p7ka7emajvydnyjlp07", name: "chainodetech", weight: 15}, + {address: "celestiavaloper1s0lankh33kprer2l22nank5rvsuh9ksa2xcd2y", name: "encapsulate(fkakingsuper)", weight: 15}, + {address: "celestiavaloper1q8teur40emyun60et4wh5z6yj5669stgz8xs59", name: "moonlet", weight: 15}, + {address: "celestiavaloper1yecxnyegvgm5dwsx0r3jsgr74ju6mlxdwkxx8g", name: "meria", weight: 15}, + {address: "celestiavaloper1cmaga4f6f7pttuwzfldn9067ld3090uw0e6zq8", name: "wavefive", weight: 15}, + {address: "celestiavaloper10f8l8m4879h40848rsvxat797t3a5ghgdsjgzl", name: "conqueror", weight: 15}, + {address: "celestiavaloper139mu0a0ucz0gmrkavm5wjar2lpx7yvxq3e25e5", name: "noders", weight: 15}, + {address: "celestiavaloper1l0zmpm02u240crndlj7hkvlj5azuglv4emfczt", name: "stakesquid", weight: 15}, + {address: "celestiavaloper1qdfdh8stxpkj4zz46x2n9ejyyy9h0c86425yjm", name: "stakerspace", weight: 14}, + {address: "celestiavaloper1st4h4ymu52hwtl3s0n298t6adj0vputx8jw8xt", name: "spidey", weight: 14}, + {address: "celestiavaloper1sl97x54v0u3extuj2zrf7h0qrrtpgpslfrjjry", name: "strangelove", weight: 14}, + {address: "celestiavaloper1ax83exaawlmy5p2qn22gcynrchwdntt5xvj0qu", name: "kooltek68", weight: 13}, + {address: "celestiavaloper1vfydl5r98zev8xc7j0mus28r63jcklsu63vuah", name: "counterpoint", weight: 13}, + {address: "celestiavaloper1cqgzxhn3dqd58xexz8yley2wntdvym4emzvpd7", name: "blockscope", weight: 13}, + {address: "celestiavaloper1t345w0vxnyyrf4eh43lpd3jl7z378rtsdn9tz3", name: "activenodes", weight: 12}, + {address: "celestiavaloper1clf3nqp89h97umhl4fmcqr642jz6rszcxegjc6", name: "partnerstaking", weight: 12}, + {address: "celestiavaloper1q2kaajedxm0r5xc0twdqz6atap96502d67yjyj", name: "mhventures", weight: 10}, +} diff --git a/proto/stride/staketia/staketia.proto b/proto/stride/staketia/staketia.proto index dc70a156d5..22da9f5608 100644 --- a/proto/stride/staketia/staketia.proto +++ b/proto/stride/staketia/staketia.proto @@ -35,45 +35,8 @@ message HostZone { string safe_address_on_stride = 11 [ (cosmos_proto.scalar) = "cosmos.AddressString" ]; - // Previous redemption rate - string last_redemption_rate = 12 [ - (cosmos_proto.scalar) = "cosmos.Dec", - (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", - (gogoproto.nullable) = false - ]; - // Current redemption rate - string redemption_rate = 13 [ - (cosmos_proto.scalar) = "cosmos.Dec", - (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", - (gogoproto.nullable) = false - ]; - // Min outer redemption rate - adjusted by governance - string min_redemption_rate = 14 [ - (cosmos_proto.scalar) = "cosmos.Dec", - (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", - (gogoproto.nullable) = false - ]; - // Max outer redemption rate - adjusted by governance - string max_redemption_rate = 15 [ - (cosmos_proto.scalar) = "cosmos.Dec", - (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", - (gogoproto.nullable) = false - ]; - // Min inner redemption rate - adjusted by controller - string min_inner_redemption_rate = 16 [ - (cosmos_proto.scalar) = "cosmos.Dec", - (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", - (gogoproto.nullable) = false - ]; - // Max inner redemption rate - adjusted by controller - string max_inner_redemption_rate = 17 [ - (cosmos_proto.scalar) = "cosmos.Dec", - (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Dec", - (gogoproto.nullable) = false - ]; - // Total delegated balance on the host zone delegation account - string delegated_balance = 18 [ + string remaining_delegated_balance = 18 [ (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int", (gogoproto.nullable) = false ]; @@ -82,6 +45,8 @@ message HostZone { uint64 unbonding_period_seconds = 19; // Indicates whether the host zone has been halted bool halted = 20; + + reserved 13; } // Status fields for a delegation record diff --git a/proto/stride/staketia/tx.proto b/proto/stride/staketia/tx.proto index b9caaaf77f..f5ec04d513 100644 --- a/proto/stride/staketia/tx.proto +++ b/proto/stride/staketia/tx.proto @@ -75,10 +75,12 @@ service Msg { returns (MsgSetOperatorAddressResponse); } +// Deprecated: Liquid stakes should be handled in stakeibc // LiquidStake message MsgLiquidStake { option (cosmos.msg.v1.signer) = "staker"; option (amino.name) = "staketia/MsgLiquidStake"; + option deprecated = true; string staker = 1; string native_amount = 2 [ @@ -87,6 +89,8 @@ message MsgLiquidStake { ]; } message MsgLiquidStakeResponse { + option deprecated = true; + cosmos.base.v1beta1.Coin st_token = 1 [ (gogoproto.nullable) = false, (gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins" @@ -103,6 +107,9 @@ message MsgRedeemStake { (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int", (gogoproto.nullable) = false ]; + // The receiver field is a celestia address + // It is only used in the case where the redemption spills over to stakeibc + string receiver = 3; } message MsgRedeemStakeResponse { cosmos.base.v1beta1.Coin native_token = 1 [ diff --git a/scripts/version.sh b/scripts/version.sh index 47e2981e0c..cbd4f6b14e 100755 --- a/scripts/version.sh +++ b/scripts/version.sh @@ -50,15 +50,15 @@ update_version ./scripts/protocgen.sh echo ">>> Committing changes..." -git add . -git commit -m "updated package from $OLD_VERSION -> $NEW_VERSION" +# git add . +# git commit -m "updated package from $OLD_VERSION -> $NEW_VERSION" # Re-generate protos echo ">>> Rebuilding protos..." make proto-all -git add . -git commit -m 'generated protos' +# git add . +# git commit -m 'generated protos' echo "Done" \ No newline at end of file diff --git a/x/stakeibc/keeper/msg_server_test.go b/x/stakeibc/keeper/msg_server_test.go index 0ba34e6c41..7d01b76551 100644 --- a/x/stakeibc/keeper/msg_server_test.go +++ b/x/stakeibc/keeper/msg_server_test.go @@ -150,7 +150,7 @@ func (s *KeeperTestSuite) SetupAddValidators() AddValidatorsTestCase { for _, validator := range expectedValidators { validator.Delegation = sdkmath.ZeroInt() validator.SlashQueryProgressTracker = sdkmath.ZeroInt() - validator.SharesToTokensRate = sdk.ZeroDec() + validator.SharesToTokensRate = sdk.OneDec() validator.SlashQueryCheckpoint = expectedSlashCheckpoint } diff --git a/x/stakeibc/keeper/validator.go b/x/stakeibc/keeper/validator.go index e03d78dc0a..3ce75e50f9 100644 --- a/x/stakeibc/keeper/validator.go +++ b/x/stakeibc/keeper/validator.go @@ -60,12 +60,15 @@ func (k Keeper) AddValidatorToHostZone(ctx sdk.Context, chainId string, validato // Finally, add the validator to the host hostZone.Validators = append(hostZone.Validators, &types.Validator{ - Name: validator.Name, - Address: validator.Address, - Weight: valWeight, - Delegation: sdkmath.ZeroInt(), - SlashQueryProgressTracker: sdkmath.ZeroInt(), - SlashQueryCheckpoint: checkpoint, + Name: validator.Name, + Address: validator.Address, + Weight: valWeight, + Delegation: sdkmath.ZeroInt(), + SlashQueryProgressTracker: sdkmath.ZeroInt(), + SlashQueryCheckpoint: checkpoint, + SharesToTokensRate: sdk.OneDec(), + DelegationChangesInProgress: 0, + SlashQueryInProgress: false, }) k.SetHostZone(ctx, hostZone) diff --git a/x/staketia/client/cli/tx.go b/x/staketia/client/cli/tx.go index 82d66e21b7..3f0408a968 100644 --- a/x/staketia/client/cli/tx.go +++ b/x/staketia/client/cli/tx.go @@ -36,7 +36,6 @@ func GetTxCmd() *cobra.Command { } cmd.AddCommand( - CmdLiquidStake(), CmdRedeemStake(), CmdConfirmDelegation(), CmdConfirmUndelegation(), @@ -52,52 +51,10 @@ func GetTxCmd() *cobra.Command { return cmd } -// User transaction to liquid stake native tokens into stTokens -func CmdLiquidStake() *cobra.Command { - cmd := &cobra.Command{ - Use: "liquid-stake [amount]", - Short: "Liquid stakes native tokens and receives stTokens", - Long: strings.TrimSpace( - fmt.Sprintf(`Liquid stakes native tokens and receives stTokens - -Example: - $ %[1]s tx %[2]s liquid-stake 10000 -`, version.AppName, types.ModuleName), - ), - Args: cobra.ExactArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - amount, ok := sdkmath.NewIntFromString(args[0]) - if !ok { - return errors.New("unable to parse amount") - } - - clientCtx, err := client.GetClientTxContext(cmd) - if err != nil { - return err - } - - msg := types.NewMsgLiquidStake( - clientCtx.GetFromAddress().String(), - amount, - ) - - if err := msg.ValidateBasic(); err != nil { - return err - } - - return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) - }, - } - - flags.AddTxFlagsToCmd(cmd) - - return cmd -} - // User transaction to redeem stake stTokens into native tokens func CmdRedeemStake() *cobra.Command { cmd := &cobra.Command{ - Use: "redeem-stake [amount]", + Use: "redeem-stake [amount] [reciever]", Short: "Redeems stTokens tokens for native tokens", Long: strings.TrimSpace( fmt.Sprintf(`Redeems stTokens tokens for native tokens. @@ -107,12 +64,13 @@ Example: $ %[1]s tx %[2]s redeem-stake 10000 `, version.AppName, types.ModuleName), ), - Args: cobra.ExactArgs(1), + Args: cobra.ExactArgs(2), RunE: func(cmd *cobra.Command, args []string) error { amount, ok := sdkmath.NewIntFromString(args[0]) if !ok { return errors.New("unable to parse amount") } + receiver := args[1] clientCtx, err := client.GetClientTxContext(cmd) if err != nil { @@ -122,6 +80,7 @@ Example: msg := types.NewMsgRedeemStake( clientCtx.GetFromAddress().String(), amount, + receiver, ) if err := msg.ValidateBasic(); err != nil { diff --git a/x/staketia/keeper/abci.go b/x/staketia/keeper/abci.go index 6e55a665c0..600ad6d012 100644 --- a/x/staketia/keeper/abci.go +++ b/x/staketia/keeper/abci.go @@ -4,13 +4,4 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" ) -func (k Keeper) BeginBlocker(ctx sdk.Context) { - // Check invariants - - // Check redemption rate is within safety bounds - if err := k.CheckRedemptionRateExceedsBounds(ctx); err != nil { - k.Logger(ctx).Error(err.Error()) - // If not, halt the zone - k.HaltZone(ctx) - } -} +func (k Keeper) BeginBlocker(ctx sdk.Context) {} diff --git a/x/staketia/keeper/delegation.go b/x/staketia/keeper/delegation.go index 163641a6d1..fabb5a7078 100644 --- a/x/staketia/keeper/delegation.go +++ b/x/staketia/keeper/delegation.go @@ -1,81 +1,16 @@ package keeper import ( - "fmt" "time" errorsmod "cosmossdk.io/errors" - sdkmath "cosmossdk.io/math" sdk "github.com/cosmos/cosmos-sdk/types" - authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" transfertypes "github.com/cosmos/ibc-go/v7/modules/apps/transfer/types" "github.com/Stride-Labs/stride/v24/utils" - stakeibctypes "github.com/Stride-Labs/stride/v24/x/stakeibc/types" "github.com/Stride-Labs/stride/v24/x/staketia/types" ) -// Liquid stakes native tokens and returns stTokens to the user -// The staker's native tokens (which exist as an IBC denom on stride) are escrowed -// in the deposit account -// StTokens are minted at the current redemption rate -func (k Keeper) LiquidStake(ctx sdk.Context, liquidStaker string, nativeAmount sdkmath.Int) (stToken sdk.Coin, err error) { - // Get the host zone and verify it's unhalted - hostZone, err := k.GetUnhaltedHostZone(ctx) - if err != nil { - return stToken, err - } - - // Get user and deposit account addresses - liquidStakerAddress, err := sdk.AccAddressFromBech32(liquidStaker) - if err != nil { - return stToken, errorsmod.Wrapf(err, "user's address is invalid") - } - hostZoneDepositAddress, err := sdk.AccAddressFromBech32(hostZone.DepositAddress) - if err != nil { - return stToken, errorsmod.Wrapf(err, "host zone deposit address is invalid") - } - - // Check redemption rates are within safety bounds - if err := k.CheckRedemptionRateExceedsBounds(ctx); err != nil { - return stToken, err - } - - // The tokens that are sent to the protocol are denominated in the ibc hash of the native token on stride (e.g. ibc/xxx) - nativeToken := sdk.NewCoin(hostZone.NativeTokenIbcDenom, nativeAmount) - if !utils.IsIBCToken(hostZone.NativeTokenIbcDenom) { - return stToken, errorsmod.Wrapf(stakeibctypes.ErrInvalidToken, - "denom is not an IBC token (%s)", hostZone.NativeTokenIbcDenom) - } - - // Determine the amount of stTokens to mint using the redemption rate - stAmount := (sdk.NewDecFromInt(nativeAmount).Quo(hostZone.RedemptionRate)).TruncateInt() - if stAmount.IsZero() { - return stToken, errorsmod.Wrapf(stakeibctypes.ErrInsufficientLiquidStake, - "Liquid stake of %s%s would return 0 stTokens", nativeAmount.String(), hostZone.NativeTokenDenom) - } - - // Transfer the native tokens from the user to module account - if err := k.bankKeeper.SendCoins(ctx, liquidStakerAddress, hostZoneDepositAddress, sdk.NewCoins(nativeToken)); err != nil { - return stToken, errorsmod.Wrapf(err, "failed to send tokens from liquid staker %s to deposit address", liquidStaker) - } - - // Mint the stTokens and transfer them to the user - stDenom := utils.StAssetDenomFromHostZoneDenom(hostZone.NativeTokenDenom) - stToken = sdk.NewCoin(stDenom, stAmount) - if err := k.bankKeeper.MintCoins(ctx, types.ModuleName, sdk.NewCoins(stToken)); err != nil { - return stToken, errorsmod.Wrapf(err, "Failed to mint stTokens") - } - if err := k.bankKeeper.SendCoinsFromModuleToAccount(ctx, types.ModuleName, liquidStakerAddress, sdk.NewCoins(stToken)); err != nil { - return stToken, errorsmod.Wrapf(err, "Failed to send %s from deposit address to liquid staker", stToken.String()) - } - - // Emit liquid stake event with the same schema as stakeibc - EmitSuccessfulLiquidStakeEvent(ctx, liquidStaker, hostZone, nativeAmount, stAmount) - - return stToken, nil -} - // IBC transfers all TIA in the deposit account and sends it to the delegation account func (k Keeper) PrepareDelegation(ctx sdk.Context, epochNumber uint64, epochDuration time.Duration) error { k.Logger(ctx).Info(utils.LogWithHostZone(types.CelestiaChainId, "Preparing delegation for epoch %d", epochNumber)) @@ -159,6 +94,10 @@ func (k Keeper) ConfirmDelegation(ctx sdk.Context, recordId uint64, txHash strin if err != nil { return err } + stakeibcHostZone, err := k.stakeibcKeeper.GetActiveHostZone(ctx, types.CelestiaChainId) + if err != nil { + return err + } // verify delegation record is nonzero if !delegationRecord.NativeAmount.IsPositive() { @@ -171,55 +110,18 @@ func (k Keeper) ConfirmDelegation(ctx sdk.Context, recordId uint64, txHash strin k.ArchiveDelegationRecord(ctx, delegationRecord) // increment delegation on Host Zone - hostZone.DelegatedBalance = hostZone.DelegatedBalance.Add(delegationRecord.NativeAmount) + hostZone.RemainingDelegatedBalance = hostZone.RemainingDelegatedBalance.Add(delegationRecord.NativeAmount) + stakeibcHostZone.TotalDelegations = stakeibcHostZone.TotalDelegations.Add(delegationRecord.NativeAmount) k.SetHostZone(ctx, hostZone) + k.stakeibcKeeper.SetHostZone(ctx, stakeibcHostZone) EmitSuccessfulConfirmDelegationEvent(ctx, recordId, delegationRecord.NativeAmount, txHash, sender) return nil } -// Liquid stakes tokens in the fee account and distributes them to the fee collector -func (k Keeper) LiquidStakeAndDistributeFees(ctx sdk.Context) error { - // Get the fee address from the host zone - hostZone, err := k.GetUnhaltedHostZone(ctx) - if err != nil { - return err - } - - // Get the balance of native tokens in the fee address, if there are no tokens, no action is necessary - feeAddress := k.accountKeeper.GetModuleAddress(types.FeeAddress) - feesBalance := k.bankKeeper.GetBalance(ctx, feeAddress, hostZone.NativeTokenIbcDenom) - if feesBalance.IsZero() { - k.Logger(ctx).Info("No fees generated this epoch") - return nil - } - - // Liquid stake those native tokens - stTokens, err := k.LiquidStake(ctx, feeAddress.String(), feesBalance.Amount) - if err != nil { - return errorsmod.Wrapf(err, "unable to liquid stake fees") - } - - // Send the stTokens to the fee collector - err = k.bankKeeper.SendCoinsFromModuleToModule(ctx, types.FeeAddress, authtypes.FeeCollectorName, sdk.NewCoins(stTokens)) - if err != nil { - return errorsmod.Wrapf(err, "unable to send liquid staked tokens to fee collector") - } - k.Logger(ctx).Info(fmt.Sprintf("Liquid staked and sent %v to fee collector", stTokens)) - - return nil -} - // Runs prepare delegations with a cache context wrapper so revert any partial state changes func (k Keeper) SafelyPrepareDelegation(ctx sdk.Context, epochNumber uint64, epochDuration time.Duration) error { return utils.ApplyFuncIfNoError(ctx, func(ctx sdk.Context) error { return k.PrepareDelegation(ctx, epochNumber, epochDuration) }) } - -// Liquid stakes fees with a cache context wrapper so revert any partial state changes -func (k Keeper) SafelyLiquidStakeAndDistributeFees(ctx sdk.Context) error { - return utils.ApplyFuncIfNoError(ctx, func(ctx sdk.Context) error { - return k.LiquidStakeAndDistributeFees(ctx) - }) -} diff --git a/x/staketia/keeper/delegation_test.go b/x/staketia/keeper/delegation_test.go index b7eff210bb..3ef3de5a2a 100644 --- a/x/staketia/keeper/delegation_test.go +++ b/x/staketia/keeper/delegation_test.go @@ -5,233 +5,15 @@ import ( sdkmath "cosmossdk.io/math" sdk "github.com/cosmos/cosmos-sdk/types" - authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" transfertypes "github.com/cosmos/ibc-go/v7/modules/apps/transfer/types" ibctesting "github.com/cosmos/ibc-go/v7/testing" + stakeibctypes "github.com/Stride-Labs/stride/v24/x/stakeibc/types" "github.com/Stride-Labs/stride/v24/x/staketia/types" ) var InitialDelegation = sdkmath.NewInt(1_000_000) -type LiquidStakeTestCase struct { - liquidStakeAmount sdkmath.Int - expectedStAmount sdkmath.Int - stakerAddress sdk.AccAddress - depositAddress sdk.AccAddress -} - -// ---------------------------------------------------- -// LiquidStake -// ---------------------------------------------------- - -// Helper function to mock relevant state before testing a liquid stake -func (s *KeeperTestSuite) SetupTestLiquidStake( - redemptionRate sdk.Dec, - liquidStakeAmount, - expectedStAmount sdkmath.Int, -) LiquidStakeTestCase { - // Create relevant addresses - stakerAddress := s.TestAccs[0] - depositAddress := s.TestAccs[1] - - // Create a host zone with relevant denom's and addresses - s.App.StaketiaKeeper.SetHostZone(s.Ctx, types.HostZone{ - ChainId: HostChainId, - NativeTokenDenom: HostNativeDenom, - NativeTokenIbcDenom: HostIBCDenom, - DepositAddress: depositAddress.String(), - RedemptionRate: redemptionRate, - MinRedemptionRate: redemptionRate.Sub(sdk.MustNewDecFromStr("0.2")), - MinInnerRedemptionRate: redemptionRate.Sub(sdk.MustNewDecFromStr("0.1")), - MaxInnerRedemptionRate: redemptionRate.Add(sdk.MustNewDecFromStr("0.1")), - MaxRedemptionRate: redemptionRate.Add(sdk.MustNewDecFromStr("0.2")), - }) - - // Fund the staker - liquidStakeToken := sdk.NewCoin(HostIBCDenom, liquidStakeAmount) - s.FundAccount(stakerAddress, liquidStakeToken) - - return LiquidStakeTestCase{ - liquidStakeAmount: liquidStakeAmount, - expectedStAmount: expectedStAmount, - stakerAddress: stakerAddress, - depositAddress: depositAddress, - } -} - -// Helper function to setup the state with default values -// (useful when testing error cases) -func (s *KeeperTestSuite) DefaultSetupTestLiquidStake() LiquidStakeTestCase { - redemptionRate := sdk.MustNewDecFromStr("1.0") - liquidStakeAmount := sdkmath.NewInt(1000) - stAmount := sdkmath.NewInt(1000) - return s.SetupTestLiquidStake(redemptionRate, liquidStakeAmount, stAmount) -} - -// Helper function to confirm balances after a successful liquid stake -func (s *KeeperTestSuite) ConfirmLiquidStakeTokenTransfer(tc LiquidStakeTestCase) { - zeroNativeTokens := sdk.NewCoin(HostIBCDenom, sdk.ZeroInt()) - liquidStakedNativeTokens := sdk.NewCoin(HostIBCDenom, tc.liquidStakeAmount) - - zeroStTokens := sdk.NewCoin(StDenom, sdk.ZeroInt()) - liquidStakedStTokens := sdk.NewCoin(StDenom, tc.expectedStAmount) - - // Confirm native tokens were escrowed - // Staker balance should have decreased to zero - // Deposit balance should have increased by liquid stake amount - stakerNativeBalance := s.App.BankKeeper.GetBalance(s.Ctx, tc.stakerAddress, HostIBCDenom) - s.CompareCoins(zeroNativeTokens, stakerNativeBalance, "staker native balance") - - depositNativeBalance := s.App.BankKeeper.GetBalance(s.Ctx, tc.depositAddress, HostIBCDenom) - s.CompareCoins(liquidStakedNativeTokens, depositNativeBalance, "deposit native balance") - - // Confirm stTokens were minted to the user - // Staker balance should increase by the liquid stake amount - // Deposit balance should still be zero - stakerStBalance := s.App.BankKeeper.GetBalance(s.Ctx, tc.stakerAddress, StDenom) - s.CompareCoins(liquidStakedStTokens, stakerStBalance, "staker stToken balance") - - depositStBalance := s.App.BankKeeper.GetBalance(s.Ctx, tc.depositAddress, StDenom) - s.CompareCoins(zeroStTokens, depositStBalance, "deposit native balance") -} - -func (s *KeeperTestSuite) TestLiquidStake_Successful() { - // Test liquid stake across different redemption rates - testCases := []struct { - name string - redemptionRate sdk.Dec - liquidStakeAmount sdkmath.Int - expectedStAmount sdkmath.Int - }{ - { - // Redemption Rate of 1: - // 1000 native -> 1000 stTokens - name: "redemption rate of 1", - redemptionRate: sdk.MustNewDecFromStr("1.0"), - liquidStakeAmount: sdkmath.NewInt(1000), - expectedStAmount: sdkmath.NewInt(1000), - }, - { - // Redemption Rate of 2: - // 1000 native -> 500 stTokens - name: "redemption rate of 2", - redemptionRate: sdk.MustNewDecFromStr("2.0"), - liquidStakeAmount: sdkmath.NewInt(1000), - expectedStAmount: sdkmath.NewInt(500), - }, - { - // Redemption Rate of 0.5: - // 1000 native -> 2000 stTokens - name: "redemption rate of 0.5", - redemptionRate: sdk.MustNewDecFromStr("0.5"), - liquidStakeAmount: sdkmath.NewInt(1000), - expectedStAmount: sdkmath.NewInt(2000), - }, - { - // Redemption Rate of 1.1: - // 333 native -> 302.72 (302) stTokens - name: "int truncation", - redemptionRate: sdk.MustNewDecFromStr("1.1"), - liquidStakeAmount: sdkmath.NewInt(333), - expectedStAmount: sdkmath.NewInt(302), - }, - } - - for _, testCase := range testCases { - s.Run(testCase.name, func() { - s.SetupTest() // reset state - tc := s.SetupTestLiquidStake(testCase.redemptionRate, testCase.liquidStakeAmount, testCase.expectedStAmount) - - // Confirm liquid stake succeeded - stTokenResponse, err := s.App.StaketiaKeeper.LiquidStake(s.Ctx, tc.stakerAddress.String(), tc.liquidStakeAmount) - s.Require().NoError(err, "no error expected during liquid stake") - - // Confirm the stToken from the response matches expectations - s.Require().Equal(StDenom, stTokenResponse.Denom, "st token denom in liquid stake response") - s.Require().Equal(tc.expectedStAmount.Int64(), stTokenResponse.Amount.Int64(), - "st token amount in liquid stake response") - - // Confirm the native token escrow and stToken mint succeeded - s.ConfirmLiquidStakeTokenTransfer(tc) - }) - } -} - -func (s *KeeperTestSuite) TestLiquidStake_HostZoneHalted() { - tc := s.DefaultSetupTestLiquidStake() - - // Halt the host zone so the liquid stake fails - hostZone := s.MustGetHostZone() - hostZone.Halted = true - s.App.StaketiaKeeper.SetHostZone(s.Ctx, hostZone) - - _, err := s.App.StaketiaKeeper.LiquidStake(s.Ctx, tc.stakerAddress.String(), tc.liquidStakeAmount) - s.Require().ErrorContains(err, "host zone is halted") -} - -func (s *KeeperTestSuite) TestLiquidStake_InvalidAddresse() { - tc := s.DefaultSetupTestLiquidStake() - - // Pass an invalid staker address and confirm it fails - _, err := s.App.StaketiaKeeper.LiquidStake(s.Ctx, "invalid_address", tc.liquidStakeAmount) - s.Require().ErrorContains(err, "user's address is invalid") - - // Set an invalid deposit address and confirm it fails - hostZone := s.MustGetHostZone() - hostZone.DepositAddress = "invalid_address" - s.App.StaketiaKeeper.SetHostZone(s.Ctx, hostZone) - - _, err = s.App.StaketiaKeeper.LiquidStake(s.Ctx, tc.stakerAddress.String(), tc.liquidStakeAmount) - s.Require().ErrorContains(err, "host zone deposit address is invalid") -} - -func (s *KeeperTestSuite) TestLiquidStake_InvalidRedemptionRate() { - tc := s.DefaultSetupTestLiquidStake() - - // Update the redemption rate so it exceeds the bounds - hostZone := s.MustGetHostZone() - hostZone.RedemptionRate = hostZone.MaxInnerRedemptionRate.Add(sdk.MustNewDecFromStr("0.01")) - s.App.StaketiaKeeper.SetHostZone(s.Ctx, hostZone) - - _, err := s.App.StaketiaKeeper.LiquidStake(s.Ctx, tc.stakerAddress.String(), tc.liquidStakeAmount) - s.Require().ErrorContains(err, "redemption rate outside inner safety bounds") -} - -func (s *KeeperTestSuite) TestLiquidStake_InvalidIBCDenom() { - tc := s.DefaultSetupTestLiquidStake() - - // Set an invalid IBC denom on the host so the liquid stake fails - hostZone := s.MustGetHostZone() - hostZone.NativeTokenIbcDenom = "non-ibc-denom" - s.App.StaketiaKeeper.SetHostZone(s.Ctx, hostZone) - - _, err := s.App.StaketiaKeeper.LiquidStake(s.Ctx, tc.stakerAddress.String(), tc.liquidStakeAmount) - s.Require().ErrorContains(err, "denom is not an IBC token") -} - -func (s *KeeperTestSuite) TestLiquidStake_InsufficientLiquidStake() { - // Adjust redemption rate so that a small liquid stake will result in 0 stTokens - // stTokens = 1(amount) / 1.1(RR) = rounds down to 0 - redemptionRate := sdk.MustNewDecFromStr("1.1") - liquidStakeAmount := sdkmath.NewInt(1) - expectedStAmount := sdkmath.ZeroInt() - tc := s.SetupTestLiquidStake(redemptionRate, liquidStakeAmount, expectedStAmount) - - _, err := s.App.StaketiaKeeper.LiquidStake(s.Ctx, tc.stakerAddress.String(), tc.liquidStakeAmount) - s.Require().ErrorContains(err, "Liquid staked amount is too small") -} - -func (s *KeeperTestSuite) TestLiquidStake_InsufficientFunds() { - // Attempt to liquid stake more tokens than the staker has available - tc := s.DefaultSetupTestLiquidStake() - - excessiveLiquidStakeAmount := sdkmath.NewInt(10000000000) - _, err := s.App.StaketiaKeeper.LiquidStake(s.Ctx, tc.stakerAddress.String(), excessiveLiquidStakeAmount) - s.Require().ErrorContains(err, "failed to send tokens from liquid staker") - s.Require().ErrorContains(err, "insufficient funds") -} - // ---------------------------------------------------- // PrepareDelegation // ---------------------------------------------------- @@ -370,10 +152,18 @@ func (s *KeeperTestSuite) SetupDelegationRecords() { s.App.StaketiaKeeper.SetDelegationRecord(s.Ctx, delegationRecord) } - // Set HostZone + // Set staketia hostZone hostZone := s.initializeHostZone() - hostZone.DelegatedBalance = InitialDelegation + hostZone.RemainingDelegatedBalance = InitialDelegation s.App.StaketiaKeeper.SetHostZone(s.Ctx, hostZone) + + // Set stakeibc host zone with the same total delegation + stakeibcHostZone := stakeibctypes.HostZone{ + ChainId: types.CelestiaChainId, + TotalDelegations: InitialDelegation, + Halted: false, + } + s.App.StakeibcKeeper.SetHostZone(s.Ctx, stakeibcHostZone) } func (s *KeeperTestSuite) VerifyDelegationRecords(verifyIdentical bool, archiveIds ...uint64) { @@ -415,7 +205,7 @@ func (s *KeeperTestSuite) VerifyDelegationRecords(verifyIdentical bool, archiveI // if nothing should have changed, verify that host zone balance is unmodified if verifyIdentical { // verify hostZone delegated balance is same as initial delegation - s.Require().Equal(InitialDelegation.Int64(), hostZone.DelegatedBalance.Int64(), "hostZone delegated balance should not have changed") + s.Require().Equal(InitialDelegation.Int64(), hostZone.RemainingDelegatedBalance.Int64(), "hostZone delegated balance should not have changed") } } } @@ -438,8 +228,14 @@ func (s *KeeperTestSuite) TestConfirmDelegation_Successful() { s.Require().Equal(ValidTxHashNew, loadedDelegationRecord.TxHash, "delegation record should be updated with txHash") // verify hostZone delegated balance is same as initial delegation + 6000 + expectedDelegation := InitialDelegation.Int64() + 6000 + hostZone := s.MustGetHostZone() - s.Require().Equal(InitialDelegation.Int64()+6000, hostZone.DelegatedBalance.Int64(), "hostZone delegated balance should have increased by 6000") + s.Require().Equal(expectedDelegation, hostZone.RemainingDelegatedBalance.Int64(), "staketia remaining delegated balance") + + stakeibcHostZone, found := s.App.StakeibcKeeper.GetHostZone(s.Ctx, types.CelestiaChainId) + s.Require().True(found) + s.Require().Equal(expectedDelegation, stakeibcHostZone.TotalDelegations.Int64(), "stakeibc total delegations") } func (s *KeeperTestSuite) TestConfirmDelegation_DelegationZero() { @@ -489,62 +285,3 @@ func (s *KeeperTestSuite) TestConfirmDelegation_RecordIncorrectState() { s.VerifyDelegationRecords(true) } } - -// ---------------------------------------------------- -// LiquidStakeAndDistributeFees -// ---------------------------------------------------- - -func (s *KeeperTestSuite) TestLiquidStakeAndDistributeFees() { - // Create relevant addresses - depositAddress := s.TestAccs[0] - feeAddress := s.App.AccountKeeper.GetModuleAddress(types.FeeAddress) - - // Liquid stake 1000 with a RR of 2, should return 500 tokens - liquidStakeAmount := sdkmath.NewInt(1000) - redemptionRate := sdk.NewDec(2) - expectedStTokens := sdkmath.NewInt(500) - - // Create a host zone with relevant denom's and addresses - hostZone := types.HostZone{ - ChainId: HostChainId, - NativeTokenDenom: HostNativeDenom, - NativeTokenIbcDenom: HostIBCDenom, - DepositAddress: depositAddress.String(), - RedemptionRate: redemptionRate, - MinRedemptionRate: redemptionRate.Sub(sdk.MustNewDecFromStr("0.2")), - MinInnerRedemptionRate: redemptionRate.Sub(sdk.MustNewDecFromStr("0.1")), - MaxInnerRedemptionRate: redemptionRate.Add(sdk.MustNewDecFromStr("0.1")), - MaxRedemptionRate: redemptionRate.Add(sdk.MustNewDecFromStr("0.2")), - } - s.App.StaketiaKeeper.SetHostZone(s.Ctx, hostZone) - - // Fund the fee address with native tokens - liquidStakeToken := sdk.NewCoin(HostIBCDenom, liquidStakeAmount) - s.FundAccount(feeAddress, liquidStakeToken) - - // Call liquid stake and distribute - err := s.App.StaketiaKeeper.LiquidStakeAndDistributeFees(s.Ctx) - s.Require().NoError(err, "no error expected when liquid staking fee tokens") - - // Confirm stTokens were sent to the fee collector - feeCollectorAddress := s.App.AccountKeeper.GetModuleAddress(authtypes.FeeCollectorName) - feeCollectorBalance := s.App.BankKeeper.GetBalance(s.Ctx, feeCollectorAddress, StDenom) - s.Require().Equal(expectedStTokens.Int64(), feeCollectorBalance.Amount.Int64(), - "fee collector should have received sttokens") - - // Attempt to liquid stake again when there are no more rewards, it should succeed but do nothing - err = s.App.StaketiaKeeper.LiquidStakeAndDistributeFees(s.Ctx) - s.Require().NoError(err, "no error expected when liquid staking again") - - feeCollectorBalance = s.App.BankKeeper.GetBalance(s.Ctx, feeCollectorAddress, StDenom) - s.Require().Equal(expectedStTokens.Int64(), feeCollectorBalance.Amount.Int64(), - "fee collector should not have changed") - - // Test that if the host zone is halted, it will error - haltedHostZone := hostZone - haltedHostZone.Halted = true - s.App.StaketiaKeeper.SetHostZone(s.Ctx, haltedHostZone) - - err = s.App.StaketiaKeeper.LiquidStakeAndDistributeFees(s.Ctx) - s.Require().ErrorContains(err, "host zone is halted") -} diff --git a/x/staketia/keeper/events.go b/x/staketia/keeper/events.go index 777d6e2635..7236fe4155 100644 --- a/x/staketia/keeper/events.go +++ b/x/staketia/keeper/events.go @@ -90,7 +90,6 @@ func EmitHaltZoneEvent(ctx sdk.Context, hostZone types.HostZone) { sdk.NewEvent( types.EventTypeHostZoneHalt, sdk.NewAttribute(types.AttributeKeyHostZone, hostZone.ChainId), - sdk.NewAttribute(types.AttributeKeyRedemptionRate, hostZone.RedemptionRate.String()), ), ) } diff --git a/x/staketia/keeper/hooks.go b/x/staketia/keeper/hooks.go index 2ed771c4cd..9e928de298 100644 --- a/x/staketia/keeper/hooks.go +++ b/x/staketia/keeper/hooks.go @@ -23,25 +23,6 @@ func (k Keeper) BeforeEpochStart(ctx sdk.Context, epochInfo epochstypes.EpochInf // Every day, refresh the redemption rate and prepare delegations // Every 4 days, prepare undelegations if epochInfo.Identifier == epochstypes.DAY_EPOCH { - // Update the redemption rate - // If this fails, do not proceed to the delegation or undelegation step - // Note: This must be run first because it is used when refreshing the native token - // balance in prepare undelegation - if err := k.UpdateRedemptionRate(ctx); err != nil { - k.Logger(ctx).Error(fmt.Sprintf("Unable update redemption rate: %s", err.Error())) - return - } - - // Post the redemption rate to the oracle (if it doesn't exceed the bounds) - if err := k.PostRedemptionRateToOracles(ctx); err != nil { - k.Logger(ctx).Error(fmt.Sprintf("Unable to post redemption rate to oracle: %s", err.Error())) - } - - // Prepare delegations by transferring the deposited tokens to the host zone - if err := k.SafelyPrepareDelegation(ctx, epochNumber, epochInfo.Duration); err != nil { - k.Logger(ctx).Error(fmt.Sprintf("Unable to prepare delegation for epoch %d: %s", epochNumber, err.Error())) - } - // Every few days (depending on the unbonding frequency) prepare undelegations which // freezes the accumulating unbonding record and refreshes the native token amount // TODO [cleanup]: replace with unbonding frequency @@ -62,13 +43,6 @@ func (k Keeper) BeforeEpochStart(ctx sdk.Context, epochInfo epochstypes.EpochInf k.Logger(ctx).Error(fmt.Sprintf("Unable to distribute claims for epoch %d: %s", epochNumber, err.Error())) } } - - // Every mint epoch, liquid stake fees and distribute to fee collector - if epochInfo.Identifier == epochstypes.MINT_EPOCH { - if err := k.SafelyLiquidStakeAndDistributeFees(ctx); err != nil { - k.Logger(ctx).Error(fmt.Sprintf("Unable to liquid stake and distribute fees this epoch %d: %s", epochNumber, err.Error())) - } - } } type Hooks struct { diff --git a/x/staketia/keeper/host_zone_test.go b/x/staketia/keeper/host_zone_test.go index d6b67f7bcf..e485349848 100644 --- a/x/staketia/keeper/host_zone_test.go +++ b/x/staketia/keeper/host_zone_test.go @@ -9,23 +9,17 @@ import ( // Helper function to create the singleton HostZone with attributes func (s *KeeperTestSuite) initializeHostZone() types.HostZone { hostZone := types.HostZone{ - ChainId: "CELESTIA", - NativeTokenDenom: "utia", - NativeTokenIbcDenom: "ibc/utia", - TransferChannelId: "channel-05", - DelegationAddress: "tia0384a", - RewardAddress: "tia144f42e9", - DepositAddress: "stride8abb3e", - RedemptionAddress: "stride3400de1", - ClaimAddress: "stride00b1a83", - LastRedemptionRate: sdk.MustNewDecFromStr("1.0"), - RedemptionRate: sdk.MustNewDecFromStr("1.0"), - MinRedemptionRate: sdk.MustNewDecFromStr("0.95"), - MaxRedemptionRate: sdk.MustNewDecFromStr("1.10"), - MinInnerRedemptionRate: sdk.MustNewDecFromStr("0.97"), - MaxInnerRedemptionRate: sdk.MustNewDecFromStr("1.07"), - DelegatedBalance: sdk.NewInt(1_000_000), - Halted: false, + ChainId: "CELESTIA", + NativeTokenDenom: "utia", + NativeTokenIbcDenom: "ibc/utia", + TransferChannelId: "channel-05", + DelegationAddress: "tia0384a", + RewardAddress: "tia144f42e9", + DepositAddress: "stride8abb3e", + RedemptionAddress: "stride3400de1", + ClaimAddress: "stride00b1a83", + RemainingDelegatedBalance: sdk.NewInt(1_000_000), + Halted: false, } s.App.StaketiaKeeper.SetHostZone(s.Ctx, hostZone) return hostZone @@ -47,8 +41,7 @@ func (s *KeeperTestSuite) TestRemoveHostZone() { func (s *KeeperTestSuite) TestSetHostZone() { hostZone := s.initializeHostZone() - hostZone.RedemptionRate = hostZone.RedemptionRate.Add(sdk.MustNewDecFromStr("0.1")) - hostZone.DelegatedBalance = hostZone.DelegatedBalance.Add(sdk.NewInt(100_000)) + hostZone.RemainingDelegatedBalance = hostZone.RemainingDelegatedBalance.Add(sdk.NewInt(100_000)) s.App.StaketiaKeeper.SetHostZone(s.Ctx, hostZone) loadedHostZone := s.MustGetHostZone() diff --git a/x/staketia/keeper/invariants.go b/x/staketia/keeper/invariants.go index 5ae366daab..22edd17e71 100644 --- a/x/staketia/keeper/invariants.go +++ b/x/staketia/keeper/invariants.go @@ -24,7 +24,7 @@ func (k Keeper) HaltZone(ctx sdk.Context) { stDenom := utils.StAssetDenomFromHostZoneDenom(hostZone.NativeTokenDenom) k.ratelimitKeeper.AddDenomToBlacklist(ctx, stDenom) - k.Logger(ctx).Error(fmt.Sprintf("[INVARIANT BROKEN!!!] %s's RR is %s.", hostZone.GetChainId(), hostZone.RedemptionRate.String())) + k.Logger(ctx).Error("[INVARIANT BROKEN!!!] %s's RR is %s.", hostZone.GetChainId()) EmitHaltZoneEvent(ctx, hostZone) } diff --git a/x/staketia/keeper/keeper.go b/x/staketia/keeper/keeper.go index 98d100498b..0df6c1e3fa 100644 --- a/x/staketia/keeper/keeper.go +++ b/x/staketia/keeper/keeper.go @@ -18,6 +18,8 @@ type Keeper struct { bankKeeper types.BankKeeper icaOracleKeeper types.ICAOracleKeeper ratelimitKeeper types.RatelimitKeeper + recordsKeeper types.RecordsKeeper + stakeibcKeeper types.StakeibcKeeper transferKeeper types.TransferKeeper } @@ -28,6 +30,8 @@ func NewKeeper( bankKeeper types.BankKeeper, icaOracleKeeper types.ICAOracleKeeper, ratelimitKeeper types.RatelimitKeeper, + recordsKeeper types.RecordsKeeper, + stakeibcKeeper types.StakeibcKeeper, transferKeeper types.TransferKeeper, ) *Keeper { return &Keeper{ @@ -37,6 +41,8 @@ func NewKeeper( bankKeeper: bankKeeper, icaOracleKeeper: icaOracleKeeper, ratelimitKeeper: ratelimitKeeper, + recordsKeeper: recordsKeeper, + stakeibcKeeper: stakeibcKeeper, transferKeeper: transferKeeper, } } diff --git a/x/staketia/keeper/migration.go b/x/staketia/keeper/migration.go new file mode 100644 index 0000000000..8815482592 --- /dev/null +++ b/x/staketia/keeper/migration.go @@ -0,0 +1,267 @@ +package keeper + +import ( + "errors" + "fmt" + + errorsmod "cosmossdk.io/errors" + sdkmath "cosmossdk.io/math" + sdk "github.com/cosmos/cosmos-sdk/types" + bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper" + + "github.com/Stride-Labs/stride/v24/utils" + recordkeeper "github.com/Stride-Labs/stride/v24/x/records/keeper" + recordtypes "github.com/Stride-Labs/stride/v24/x/records/types" + stakeibckeeper "github.com/Stride-Labs/stride/v24/x/stakeibc/keeper" + stakeibctypes "github.com/Stride-Labs/stride/v24/x/stakeibc/types" + oldtypes "github.com/Stride-Labs/stride/v24/x/staketia/legacytypes" + "github.com/Stride-Labs/stride/v24/x/staketia/types" +) + +// Helper to deserialize the host zone with the old types +func (k Keeper) GetLegacyHostZone(ctx sdk.Context) (hostZone oldtypes.HostZone, err error) { + store := ctx.KVStore(k.storeKey) + hostZoneBz := store.Get(types.HostZoneKey) + + if len(hostZoneBz) == 0 { + return hostZone, types.ErrHostZoneNotFound.Wrapf("No HostZone found, there must be exactly one HostZone!") + } + + k.cdc.MustUnmarshal(hostZoneBz, &hostZone) + return hostZone, nil +} + +// Helper to deserialize store a host zone with the old type definition +// (only used for tests) +func (k Keeper) SetLegacyHostZone(ctx sdk.Context, hostZone oldtypes.HostZone) { + store := ctx.KVStore(k.storeKey) + hostZoneBz := k.cdc.MustMarshal(&hostZone) + store.Set(types.HostZoneKey, hostZoneBz) +} + +// Update the newly created stakeibc host zone with the accounting values from staketia +func (k Keeper) UpdateStakeibcHostZone(ctx sdk.Context, legacyHostZone oldtypes.HostZone) (stakeibctypes.HostZone, error) { + // Grab the newly created stakeibc host zone + stakeibcHostZone, found := k.stakeibcKeeper.GetHostZone(ctx, types.CelestiaChainId) + if !found { + return stakeibctypes.HostZone{}, errors.New("celestia host zone not found in stakeibc after registration") + } + + // Disable redemptions and set the redemption rate to the one from stakeibc + stakeibcHostZone.RedemptionsEnabled = false + stakeibcHostZone.RedemptionRate = legacyHostZone.RedemptionRate + stakeibcHostZone.MinInnerRedemptionRate = legacyHostZone.MinInnerRedemptionRate + stakeibcHostZone.MaxInnerRedemptionRate = legacyHostZone.MaxInnerRedemptionRate + stakeibcHostZone.Halted = legacyHostZone.Halted + + // Set the total delegations to the sum of the staketia total + stakeibcHostZone.TotalDelegations = legacyHostZone.DelegatedBalance + k.stakeibcKeeper.SetHostZone(ctx, stakeibcHostZone) + + return stakeibcHostZone, nil +} + +// Migrates the protocol owned accounts (deposit and fee) to their stakeibc counterparts +func (k Keeper) MigrateProtocolOwnedAccounts( + ctx sdk.Context, + legacyHostZone oldtypes.HostZone, + stakeibcHostZone stakeibctypes.HostZone, +) error { + // Transfer tokens from the staketia deposit account to the stakeibc deposit account + ctx.Logger().Info("Migrating the deposit account...") + staketiaDepositAddress, err := sdk.AccAddressFromBech32(legacyHostZone.DepositAddress) + if err != nil { + return errorsmod.Wrapf(err, "invalid staketia deposit address") + } + stakeibcDepositAddress, err := sdk.AccAddressFromBech32(stakeibcHostZone.DepositAddress) + if err != nil { + return errorsmod.Wrapf(err, "invalid stakeibc deposit address") + } + + depositBalance := k.bankKeeper.GetBalance(ctx, staketiaDepositAddress, legacyHostZone.NativeTokenIbcDenom) + err = k.bankKeeper.SendCoins(ctx, staketiaDepositAddress, stakeibcDepositAddress, sdk.NewCoins(depositBalance)) + if err != nil { + return errorsmod.Wrapf(err, "unable to transfer deposit accounts") + } + + // Add that deposit amount to the new stakeibc deposit record (in status TRANSFER_QUEUE) + celestiaDepositRecords := []recordtypes.DepositRecord{} + for _, depositRecord := range k.recordsKeeper.GetAllDepositRecord(ctx) { + if depositRecord.HostZoneId == types.CelestiaChainId { + celestiaDepositRecords = append(celestiaDepositRecords, depositRecord) + } + } + + if len(celestiaDepositRecords) != 1 || celestiaDepositRecords[0].Status != recordtypes.DepositRecord_TRANSFER_QUEUE { + return errors.New("there should only be one celestia deposit record in status TRANSFER_QUEUE") + } + + depositRecord := celestiaDepositRecords[0] + depositRecord.Amount = depositBalance.Amount + k.recordsKeeper.SetDepositRecord(ctx, depositRecord) + + // Transfer tokens from the staketia fee account to the stakeibc reward collector + ctx.Logger().Info("Migrating the fee account...") + staketiaFeeAddress := k.accountKeeper.GetModuleAddress(types.FeeAddress) + stakeibcFeeAddress := stakeibctypes.RewardCollectorName + + feesBalance := k.bankKeeper.GetBalance(ctx, staketiaFeeAddress, legacyHostZone.NativeTokenIbcDenom) + if feesBalance.IsZero() { + ctx.Logger().Info("No fees to migrate") + return nil + } + + err = k.bankKeeper.SendCoinsFromAccountToModule(ctx, staketiaFeeAddress, stakeibcFeeAddress, sdk.NewCoins(feesBalance)) + if err != nil { + return errorsmod.Wrapf(err, "unable to transfer fee accounts") + } + + return nil +} + +// Initiates the migration to stakeibc by registering the host zone +// and transferring funds to the new stakeibc accounts +// This will be called from the upgrade handler +func InitiateMigration( + ctx sdk.Context, + staketiaKeeper Keeper, + bankKeeper bankkeeper.Keeper, + recordsKeeper recordkeeper.Keeper, + stakeibcKeeper stakeibckeeper.Keeper, +) error { + ctx.Logger().Info("Initiating staketia to stakeibc migration...") + + // Deserialize the staketia host zone with the old types (to recover the redemption rates) + legacyHostZone, err := staketiaKeeper.GetLegacyHostZone(ctx) + if err != nil { + return err + } + + // Calculate the redemption rate right before the migration + initialRedemptionRate, err := GetStaketiaRedemptionRate(ctx, bankKeeper, staketiaKeeper, legacyHostZone) + if err != nil { + return err + } + + // Register the stakeibc host zone + registerMsg := stakeibctypes.MsgRegisterHostZone{ + ConnectionId: types.CelestiaConnectionId, + Bech32Prefix: types.CelestiaBechPrefix, + HostDenom: legacyHostZone.NativeTokenDenom, + IbcDenom: legacyHostZone.NativeTokenIbcDenom, + TransferChannelId: legacyHostZone.TransferChannelId, + UnbondingPeriod: types.CelestiaUnbondingPeriodDays, + MinRedemptionRate: legacyHostZone.MinRedemptionRate, + MaxRedemptionRate: legacyHostZone.MaxRedemptionRate, + LsmLiquidStakeEnabled: false, + CommunityPoolTreasuryAddress: "", + MaxMessagesPerIcaTx: 32, + } + + ctx.Logger().Info("Registering the stakeibc host zone...") + if _, err := stakeibcKeeper.RegisterHostZone(ctx, ®isterMsg); err != nil { + return errorsmod.Wrapf(err, "unable to register host zone with stakeibc") + } + + ctx.Logger().Info("Updating the stakeibc host zone...") + stakeibcHostZone, err := staketiaKeeper.UpdateStakeibcHostZone(ctx, legacyHostZone) + if err != nil { + return errorsmod.Wrapf(err, "unable to update the new stakeibc host zone") + } + + ctx.Logger().Info("Migrating protocol owned accounts...") + if err := staketiaKeeper.MigrateProtocolOwnedAccounts(ctx, legacyHostZone, stakeibcHostZone); err != nil { + return errorsmod.Wrapf(err, "unable to migrate protocol owned accounts") + } + + // Calculate the redemption rate again at the end and check that it hasn't changed + finalRedemptionRate, err := GetStakeibcRedemptionRate(ctx, bankKeeper, recordsKeeper, stakeibcKeeper, stakeibcHostZone) + if err != nil { + return err + } + + if initialRedemptionRate.Sub(finalRedemptionRate).Abs().GT(sdk.MustNewDecFromStr("0.000000001")) { + return errors.New("celestia redemption rate after upgrade did not match redemption rate from staketia ") + } + + ctx.Logger().Info("Done with staketia migration") + return nil +} + +// Direct copy of the, now deprecated, redemption rate update function that was in staketia +// This is used to verify nothing went wrong during the migration +func GetStaketiaRedemptionRate( + ctx sdk.Context, + bankKeeper bankkeeper.Keeper, + staketiaKeeper Keeper, + hostZone oldtypes.HostZone, +) (redemptionRate sdk.Dec, err error) { + // Get the number of stTokens from the supply + stTokenSupply := bankKeeper.GetSupply(ctx, utils.StAssetDenomFromHostZoneDenom(hostZone.NativeTokenDenom)).Amount + if stTokenSupply.IsZero() { + return redemptionRate, errors.New("supply of sttia was 0") + } + + // Get the balance of the deposit address + depositAddress, err := sdk.AccAddressFromBech32(hostZone.DepositAddress) + if err != nil { + return redemptionRate, errorsmod.Wrapf(err, "invalid deposit address") + } + depositAccountBalance := bankKeeper.GetBalance(ctx, depositAddress, hostZone.NativeTokenIbcDenom) + + // Then add that to the sum of the delegation records to get the undelegated balance + // Delegation records are only created once the tokens leave the deposit address + // and the record is deleted once the tokens are delegated + undelegatedBalance := sdkmath.ZeroInt() + for _, delegationRecord := range staketiaKeeper.GetAllActiveDelegationRecords(ctx) { + undelegatedBalance = undelegatedBalance.Add(delegationRecord.NativeAmount) + } + + ctx.Logger().Info(fmt.Sprintf("Staketia Redemption Rate Components - "+ + "Deposit Account Balance: %v, Undelegated Balance: %v, Native Delegations: %v, stToken Supply: %v", + depositAccountBalance, undelegatedBalance, hostZone.DelegatedBalance, stTokenSupply)) + + // Finally, calculated the redemption rate as the native tokens locked divided by the stTokens + nativeTokensLocked := depositAccountBalance.Amount.Add(undelegatedBalance).Add(hostZone.DelegatedBalance) + if !nativeTokensLocked.IsPositive() { + return redemptionRate, errors.New("Non-zero stToken supply, yet the zero delegated and undelegated balance") + } + redemptionRate = sdk.NewDecFromInt(nativeTokensLocked).Quo(sdk.NewDecFromInt(stTokenSupply)) + + ctx.Logger().Info(fmt.Sprintf("Staketia Redemption Rate %v", redemptionRate)) + + return redemptionRate, nil +} + +// Direct copy of the redemption rate update function in stakeibc +// This is used to verify nothing went wrong during the migration +func GetStakeibcRedemptionRate( + ctx sdk.Context, + bankKeeper bankkeeper.Keeper, + recordsKeeper recordkeeper.Keeper, + stakeibcKeeper stakeibckeeper.Keeper, + hostZone stakeibctypes.HostZone, +) (redemptionRate sdk.Dec, err error) { + // Gather redemption rate components + stSupply := bankKeeper.GetSupply(ctx, utils.StAssetDenomFromHostZoneDenom(hostZone.HostDenom)).Amount + if stSupply.IsZero() { + return redemptionRate, errors.New("supply of sttia was 0") + } + + depositRecords := recordsKeeper.GetAllDepositRecord(ctx) + depositAccountBalance := stakeibcKeeper.GetDepositAccountBalance(hostZone.ChainId, depositRecords) + undelegatedBalance := stakeibcKeeper.GetUndelegatedBalance(hostZone.ChainId, depositRecords) + nativeDelegation := sdk.NewDecFromInt(hostZone.TotalDelegations) + + ctx.Logger().Info(fmt.Sprintf("Stakeibc Redemption Rate Components - "+ + "Deposit Account Balance: %v, Undelegated Balance: %v, Native Delegations: %v, stToken Supply: %v", + depositAccountBalance, undelegatedBalance, nativeDelegation, stSupply)) + + // Calculate the redemption rate + nativeTokensLocked := depositAccountBalance.Add(undelegatedBalance).Add(nativeDelegation) + redemptionRate = nativeTokensLocked.Quo(sdk.NewDecFromInt(stSupply)) + + ctx.Logger().Info(fmt.Sprintf("Stakeibc Redemption Rate %v", redemptionRate)) + + return redemptionRate, nil +} diff --git a/x/staketia/keeper/migration_test.go b/x/staketia/keeper/migration_test.go new file mode 100644 index 0000000000..ad53438238 --- /dev/null +++ b/x/staketia/keeper/migration_test.go @@ -0,0 +1,200 @@ +package keeper_test + +import ( + sdkmath "cosmossdk.io/math" + sdk "github.com/cosmos/cosmos-sdk/types" + ibctesting "github.com/cosmos/ibc-go/v7/testing" + + epochtypes "github.com/Stride-Labs/stride/v24/x/epochs/types" + recordtypes "github.com/Stride-Labs/stride/v24/x/records/types" + stakeibctypes "github.com/Stride-Labs/stride/v24/x/stakeibc/types" + "github.com/Stride-Labs/stride/v24/x/staketia/keeper" + oldtypes "github.com/Stride-Labs/stride/v24/x/staketia/legacytypes" + "github.com/Stride-Labs/stride/v24/x/staketia/types" +) + +func (s *KeeperTestSuite) TestUpdateStakeibcHostZone() { + // Create a host zone with a delegated balance of 1000 + halted := true + totalDelegations := sdk.NewInt(1_000) + redemptionRate := sdk.NewDec(2) + minInnerRedemptionRate := sdk.MustNewDecFromStr("1.9") + maxInnerRedemptionRate := sdk.MustNewDecFromStr("2.1") + legacyHostZone := oldtypes.HostZone{ + RedemptionRate: redemptionRate, + DelegatedBalance: totalDelegations, + MinInnerRedemptionRate: minInnerRedemptionRate, + MaxInnerRedemptionRate: maxInnerRedemptionRate, + Halted: halted, + } + stakeibcHostZone := stakeibctypes.HostZone{ + ChainId: types.CelestiaChainId, + } + s.App.StaketiaKeeper.SetLegacyHostZone(s.Ctx, legacyHostZone) + s.App.StakeibcKeeper.SetHostZone(s.Ctx, stakeibcHostZone) + + // Call the update host zone function and confirm against expectations + actualStakeibcHostZone, err := s.App.StaketiaKeeper.UpdateStakeibcHostZone(s.Ctx, legacyHostZone) + s.Require().NoError(err, "no error expected when updating host zone") + + s.Require().Equal(types.CelestiaChainId, actualStakeibcHostZone.ChainId, "chain ID") + s.Require().Equal(totalDelegations, actualStakeibcHostZone.TotalDelegations, "total delegations") + s.Require().Equal(redemptionRate, actualStakeibcHostZone.RedemptionRate, "redemption rate") + s.Require().Equal(minInnerRedemptionRate, actualStakeibcHostZone.MinInnerRedemptionRate, "min redemption rate") + s.Require().Equal(maxInnerRedemptionRate, actualStakeibcHostZone.MaxInnerRedemptionRate, "max redemption rate") + s.Require().Equal(halted, actualStakeibcHostZone.Halted, "halted") + + // Remove the host zone and try again, it should fail + s.App.StakeibcKeeper.RemoveHostZone(s.Ctx, types.CelestiaChainId) + _, err = s.App.StaketiaKeeper.UpdateStakeibcHostZone(s.Ctx, legacyHostZone) + s.Require().ErrorContains(err, "celestia host zone not found") +} + +func (s *KeeperTestSuite) TestMigrateProtocolOwnedAccounts() { + // Create deposit accounts across both modules + staketiaDepositAccount := s.TestAccs[0] + stakeibcDepositAccount := s.TestAccs[1] + + // Get the respective fee module accounts for both modules + staketiaFeeModuleName := types.FeeAddress + stakeibcFeeAddress := s.App.AccountKeeper.GetModuleAddress(stakeibctypes.RewardCollectorName) + + // Set the addresses on the respective host zones + staketiaHostZone := oldtypes.HostZone{ + DepositAddress: staketiaDepositAccount.String(), + NativeTokenIbcDenom: HostIBCDenom, + } + stakeibcHostZone := stakeibctypes.HostZone{ + ChainId: types.CelestiaChainId, + DepositAddress: stakeibcDepositAccount.String(), + } + + // Create a deposit record that will be modified + s.App.RecordsKeeper.SetDepositRecord(s.Ctx, recordtypes.DepositRecord{ + Id: 1, + Amount: sdkmath.ZeroInt(), + HostZoneId: types.CelestiaChainId, + }) + + // Fund the deposit and fee account on staketia + denom := staketiaHostZone.NativeTokenIbcDenom + expectedDepositBalance := sdkmath.NewInt(1000) + expectedFeeBalance := sdkmath.NewInt(2000) + + s.FundAccount(staketiaDepositAccount, sdk.NewCoin(denom, expectedDepositBalance)) + s.FundModuleAccount(staketiaFeeModuleName, sdk.NewCoin(denom, expectedFeeBalance)) + + // Call the migration function to transfer to stakeibc + err := s.App.StaketiaKeeper.MigrateProtocolOwnedAccounts(s.Ctx, staketiaHostZone, stakeibcHostZone) + s.Require().NoError(err, "no error expected when migrating accounts") + + // Check that the stakeibc accounts are now funded + actualDepositBalance := s.App.BankKeeper.GetBalance(s.Ctx, stakeibcDepositAccount, denom) + s.Require().Equal(expectedDepositBalance.Int64(), actualDepositBalance.Amount.Int64(), "deposit balance") + + actualFeeBalance := s.App.BankKeeper.GetBalance(s.Ctx, stakeibcFeeAddress, denom) + s.Require().Equal(expectedFeeBalance.Int64(), actualFeeBalance.Amount.Int64(), "fee balance") + + // Confirm that the deposit record was incremented + depositRecords := s.App.RecordsKeeper.GetAllDepositRecord(s.Ctx) + s.Require().Len(depositRecords, 1, "deposit record should have been created") + s.Require().Equal(expectedDepositBalance.Int64(), depositRecords[0].Amount.Int64(), "deposit record") + + // Create a second deposit record and try to call the migration again, it should fail + s.App.RecordsKeeper.SetDepositRecord(s.Ctx, recordtypes.DepositRecord{ + Id: 2, + HostZoneId: types.CelestiaChainId, + }) + err = s.App.StaketiaKeeper.MigrateProtocolOwnedAccounts(s.Ctx, staketiaHostZone, stakeibcHostZone) + s.Require().ErrorContains(err, "there should only be one celestia deposit record") +} + +func (s *KeeperTestSuite) TestInitiateMigration() { + // Create a transfer channel (which will create a connection) + s.CreateTransferChannel(types.CelestiaChainId) + + staketiaDepositAccount := s.TestAccs[0] + staketiaFeeModuleName := types.FeeAddress + + // Fund the staketia deposit and fee accounts + depositBalance := sdkmath.NewInt(1000) + feeBalance := sdkmath.NewInt(2000) + totalDelegations := sdk.NewInt(1000) + s.FundAccount(staketiaDepositAccount, sdk.NewCoin(HostIBCDenom, depositBalance)) + s.FundModuleAccount(staketiaFeeModuleName, sdk.NewCoin(HostIBCDenom, feeBalance)) + + // Mint stTIA for the redemption rate calculation + s.FundAccount(s.TestAccs[1], sdk.NewCoin("st"+HostNativeDenom, sdk.NewInt(1000))) + + // Store the legacy host zone + legacyHostZone := oldtypes.HostZone{ + ChainId: types.CelestiaChainId, + DepositAddress: staketiaDepositAccount.String(), + NativeTokenDenom: HostNativeDenom, + NativeTokenIbcDenom: HostIBCDenom, + TransferChannelId: ibctesting.FirstChannelID, + MinRedemptionRate: sdk.MustNewDecFromStr("0.90"), + MaxRedemptionRate: sdk.MustNewDecFromStr("1.5"), + RedemptionRate: sdk.MustNewDecFromStr("1.2"), + DelegatedBalance: totalDelegations, + } + s.App.StaketiaKeeper.SetLegacyHostZone(s.Ctx, legacyHostZone) + + // Create epoch trackers and EURs which are needed for the stakeibc registration + s.App.StakeibcKeeper.SetEpochTracker(s.Ctx, stakeibctypes.EpochTracker{ + EpochIdentifier: epochtypes.DAY_EPOCH, + EpochNumber: uint64(1), + }) + s.App.StakeibcKeeper.SetEpochTracker(s.Ctx, stakeibctypes.EpochTracker{ + EpochIdentifier: epochtypes.STRIDE_EPOCH, + EpochNumber: uint64(1), + }) + epochUnbondingRecord := recordtypes.EpochUnbondingRecord{ + EpochNumber: uint64(1), + HostZoneUnbondings: []*recordtypes.HostZoneUnbonding{}, + } + s.App.RecordsKeeper.SetEpochUnbondingRecord(s.Ctx, epochUnbondingRecord) + + // Call the migration function to register with stakeibc + // Before we call it, temporarily update the variable to be connection-0 to match the above + // and then set it back after the function call for other tests that use it + mainnetConnectionId := types.CelestiaConnectionId + types.CelestiaConnectionId = ibctesting.FirstConnectionID + + err := keeper.InitiateMigration(s.Ctx, s.App.StaketiaKeeper, s.App.BankKeeper, s.App.RecordsKeeper, s.App.StakeibcKeeper) + types.CelestiaConnectionId = mainnetConnectionId + s.Require().NoError(err, "no error expected during migration") + + // Confirm the new host zone + hostZone, found := s.App.StakeibcKeeper.GetHostZone(s.Ctx, types.CelestiaChainId) + s.Require().True(found, "stakeibc host zone should have been created") + + s.Require().Equal(legacyHostZone.TransferChannelId, hostZone.TransferChannelId, "transfer channel ID") + s.Require().Equal(legacyHostZone.NativeTokenDenom, hostZone.HostDenom, "native denom") + s.Require().Equal(legacyHostZone.NativeTokenIbcDenom, hostZone.IbcDenom, "ibc denom") + + s.Require().Equal(legacyHostZone.RedemptionRate, hostZone.RedemptionRate, "redemption rate") + s.Require().Equal(legacyHostZone.MinRedemptionRate, hostZone.MinRedemptionRate, "min redemption rate") + s.Require().Equal(legacyHostZone.MaxRedemptionRate, hostZone.MaxRedemptionRate, "max redemption rate") + + s.Require().Equal(ibctesting.FirstConnectionID, hostZone.ConnectionId, "connection ID") + s.Require().Equal(types.CelestiaBechPrefix, hostZone.Bech32Prefix, "bech prefix") + s.Require().Equal(uint64(types.CelestiaUnbondingPeriodDays), hostZone.UnbondingPeriod, "unbonding period") + + s.Require().False(hostZone.RedemptionsEnabled, "redemptions enabled") + s.Require().Equal(totalDelegations, hostZone.TotalDelegations, "total delegations") + + // Confirm balances were transferred + stakeibcDepositAccount := sdk.MustAccAddressFromBech32(hostZone.DepositAddress) + actualDepositBalance := s.App.BankKeeper.GetBalance(s.Ctx, stakeibcDepositAccount, HostIBCDenom) + s.Require().Equal(depositBalance.Int64(), actualDepositBalance.Amount.Int64(), "deposit balance transfer") + + stakeibcFeeAddress := s.App.AccountKeeper.GetModuleAddress(stakeibctypes.RewardCollectorName) + actualFeeBalance := s.App.BankKeeper.GetBalance(s.Ctx, stakeibcFeeAddress, HostIBCDenom) + s.Require().Equal(feeBalance.Int64(), actualFeeBalance.Amount.Int64(), "fee balance transfer") + + // Confirm a deposit record was created with the deposit amount + depositRecords := s.App.RecordsKeeper.GetAllDepositRecord(s.Ctx) + s.Require().Len(depositRecords, 1, "deposit record should have been created") + s.Require().Equal(depositBalance.Int64(), depositRecords[0].Amount.Int64(), "deposit record") +} diff --git a/x/staketia/keeper/msg_server.go b/x/staketia/keeper/msg_server.go index 04ac5aee35..79c684ea13 100644 --- a/x/staketia/keeper/msg_server.go +++ b/x/staketia/keeper/msg_server.go @@ -2,12 +2,10 @@ package keeper import ( "context" + "errors" - errorsmod "cosmossdk.io/errors" sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/Stride-Labs/stride/v24/utils" - "github.com/Stride-Labs/stride/v24/x/staketia/types" ) @@ -24,19 +22,14 @@ func NewMsgServerImpl(keeper Keeper) types.MsgServer { var _ types.MsgServer = msgServer{} // User transaction to liquid stake native tokens into stTokens -func (k msgServer) LiquidStake(goCtx context.Context, msg *types.MsgLiquidStake) (*types.MsgLiquidStakeResponse, error) { - ctx := sdk.UnwrapSDKContext(goCtx) - stToken, err := k.Keeper.LiquidStake(ctx, msg.Staker, msg.NativeAmount) - if err != nil { - return nil, err - } - return &types.MsgLiquidStakeResponse{StToken: stToken}, nil +func (k msgServer) LiquidStake(goCtx context.Context, msg *types.MsgLiquidStake) (*types.MsgLiquidStakeResponse, error) { //nolint:staticcheck + return nil, errors.New("Liquid staking is no longer enabled in staketia, use stakeibc instead") } // User transaction to redeem stake stTokens into native tokens func (k msgServer) RedeemStake(goCtx context.Context, msg *types.MsgRedeemStake) (*types.MsgRedeemStakeResponse, error) { ctx := sdk.UnwrapSDKContext(goCtx) - nativeToken, err := k.Keeper.RedeemStake(ctx, msg.Redeemer, msg.StTokenAmount) + nativeToken, err := k.Keeper.RedeemStake(ctx, msg.Redeemer, msg.Receiver, msg.StTokenAmount) if err != nil { return nil, err } @@ -111,14 +104,26 @@ func (k msgServer) AdjustDelegatedBalance(goCtx context.Context, msg *types.MsgA if err != nil { return nil, err } - hostZone.DelegatedBalance = hostZone.DelegatedBalance.Add(msg.DelegationOffset) + hostZone.RemainingDelegatedBalance = hostZone.RemainingDelegatedBalance.Add(msg.DelegationOffset) // safety check that this will not cause the delegated balance to be negative - if hostZone.DelegatedBalance.IsNegative() { + if hostZone.RemainingDelegatedBalance.IsNegative() { return nil, types.ErrNegativeNotAllowed.Wrapf("offset would cause the delegated balance to be negative") } k.SetHostZone(ctx, hostZone) + // Repeat the same thing on the stakeibc host zone + stakeibcHostZone, found := k.stakeibcKeeper.GetHostZone(ctx, types.CelestiaChainId) + if !found { + return nil, errors.New("celestia host zone not found in stakeibc") + } + stakeibcHostZone.TotalDelegations = stakeibcHostZone.TotalDelegations.Add(msg.DelegationOffset) + + if stakeibcHostZone.TotalDelegations.IsNegative() { + return nil, types.ErrNegativeNotAllowed.Wrapf("offset would cause the delegated balance to be negative") + } + k.stakeibcKeeper.SetHostZone(ctx, stakeibcHostZone) + // create a corresponding slash record latestSlashRecordId := k.IncrementSlashRecordId(ctx) slashRecord := types.SlashRecord{ @@ -134,71 +139,14 @@ func (k msgServer) AdjustDelegatedBalance(goCtx context.Context, msg *types.MsgA // Adjusts the inner redemption rate bounds on the host zone func (k msgServer) UpdateInnerRedemptionRateBounds(goCtx context.Context, msg *types.MsgUpdateInnerRedemptionRateBounds) (*types.MsgUpdateInnerRedemptionRateBoundsResponse, error) { - ctx := sdk.UnwrapSDKContext(goCtx) - - // gate this transaction to the BOUNDS address - if err := utils.ValidateAdminAddress(msg.Creator); err != nil { - return nil, types.ErrInvalidAdmin - } - - // Fetch the zone - zone, err := k.GetHostZone(ctx) - if err != nil { - return nil, err - } - - // Get the outer bounds - maxOuterBound := zone.MaxRedemptionRate - minOuterBound := zone.MinRedemptionRate - - // Confirm the inner bounds are within the outer bounds - maxInnerBound := msg.MaxInnerRedemptionRate - minInnerBound := msg.MinInnerRedemptionRate - if maxInnerBound.GT(maxOuterBound) { - return nil, types.ErrInvalidRedemptionRateBounds - } - if minInnerBound.LT(minOuterBound) { - return nil, types.ErrInvalidRedemptionRateBounds - } - - // Set the inner bounds on the host zone - zone.MinInnerRedemptionRate = minInnerBound - zone.MaxInnerRedemptionRate = maxInnerBound - - // Update the host zone - k.SetHostZone(ctx, zone) - + _ = sdk.UnwrapSDKContext(goCtx) return &types.MsgUpdateInnerRedemptionRateBoundsResponse{}, nil } // Unhalts the host zone if redemption rates were exceeded // BOUNDS: verified in ValidateBasic func (k msgServer) ResumeHostZone(goCtx context.Context, msg *types.MsgResumeHostZone) (*types.MsgResumeHostZoneResponse, error) { - ctx := sdk.UnwrapSDKContext(goCtx) - - // gate this transaction to the BOUNDS address - if err := utils.ValidateAdminAddress(msg.Creator); err != nil { - return nil, types.ErrInvalidAdmin - } - - // Note: of course we don't want to fail this if the zone is halted! - zone, err := k.GetHostZone(ctx) - if err != nil { - return nil, err - } - - // Check the zone is halted - if !zone.Halted { - return nil, errorsmod.Wrapf(types.ErrHostZoneNotHalted, "zone is not halted") - } - - stDenom := utils.StAssetDenomFromHostZoneDenom(zone.NativeTokenDenom) - k.ratelimitKeeper.RemoveDenomFromBlacklist(ctx, stDenom) - - // Resume zone - zone.Halted = false - k.SetHostZone(ctx, zone) - + _ = sdk.UnwrapSDKContext(goCtx) return &types.MsgResumeHostZoneResponse{}, nil } @@ -211,9 +159,7 @@ func (k msgServer) RefreshRedemptionRate(goCtx context.Context, msgTriggerRedemp return nil, err } - err := k.UpdateRedemptionRate(ctx) - - return &types.MsgRefreshRedemptionRateResponse{}, err + return &types.MsgRefreshRedemptionRateResponse{}, nil } // overwrite a delegation record diff --git a/x/staketia/keeper/msg_server_test.go b/x/staketia/keeper/msg_server_test.go index ae976e3271..80750dc17f 100644 --- a/x/staketia/keeper/msg_server_test.go +++ b/x/staketia/keeper/msg_server_test.go @@ -4,35 +4,10 @@ import ( sdkmath "cosmossdk.io/math" sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/Stride-Labs/stride/v24/app/apptesting" + stakeibctypes "github.com/Stride-Labs/stride/v24/x/stakeibc/types" "github.com/Stride-Labs/stride/v24/x/staketia/types" ) -// ---------------------------------------------- -// MsgLiquidStake -// ---------------------------------------------- - -// More granular testing of liquid stake is done in the keeper function -// This just tests the msg server wrapper -func (s *KeeperTestSuite) TestMsgServerLiquidStake() { - tc := s.DefaultSetupTestLiquidStake() - - // Attempt a successful liquid stake - validMsg := types.MsgLiquidStake{ - Staker: tc.stakerAddress.String(), - NativeAmount: tc.liquidStakeAmount, - } - resp, err := s.GetMsgServer().LiquidStake(sdk.UnwrapSDKContext(s.Ctx), &validMsg) - s.Require().NoError(err, "no error expected during liquid stake") - s.Require().Equal(tc.expectedStAmount.Int64(), resp.StToken.Amount.Int64(), "stToken amount") - - s.ConfirmLiquidStakeTokenTransfer(tc) - - // Attempt a liquid stake again, it should fail now that the staker is out of funds - _, err = s.GetMsgServer().LiquidStake(sdk.UnwrapSDKContext(s.Ctx), &validMsg) - s.Require().ErrorContains(err, "insufficient funds") -} - // ---------------------------------------------- // MsgConfirmDelegation // ---------------------------------------------- @@ -182,10 +157,14 @@ func (s *KeeperTestSuite) TestAdjustDelegatedBalance() { safeAddress := "safe" - // Create the host zone + // Create the host zones s.App.StaketiaKeeper.SetHostZone(s.Ctx, types.HostZone{ - SafeAddressOnStride: safeAddress, - DelegatedBalance: sdk.NewInt(0), + SafeAddressOnStride: safeAddress, + RemainingDelegatedBalance: sdk.NewInt(0), + }) + s.App.StakeibcKeeper.SetHostZone(s.Ctx, stakeibctypes.HostZone{ + ChainId: types.CelestiaChainId, + TotalDelegations: sdk.NewInt(0), }) // we're halting the zone to test that the tx works even when the host zone is halted @@ -213,7 +192,11 @@ func (s *KeeperTestSuite) TestAdjustDelegatedBalance() { s.Require().NoError(err, "no error expected when adjusting delegated bal properly for %s", tc.address) hostZone := s.MustGetHostZone() - s.Require().Equal(tc.endDelegation, hostZone.DelegatedBalance, "delegation after change for %s", tc.address) + s.Require().Equal(tc.endDelegation, hostZone.RemainingDelegatedBalance, "remaining delegation after change for %s", tc.address) + + stakeibcHostZone, found := s.App.StakeibcKeeper.GetHostZone(s.Ctx, types.CelestiaChainId) + s.Require().True(found) + s.Require().Equal(tc.endDelegation, stakeibcHostZone.TotalDelegations, "total delegation after change for %s", tc.address) } // Attempt to call it with an amount that would make it negative, it should fail @@ -233,190 +216,6 @@ func (s *KeeperTestSuite) TestAdjustDelegatedBalance() { s.App.StaketiaKeeper.RemoveHostZone(s.Ctx) _, err = s.GetMsgServer().AdjustDelegatedBalance(s.Ctx, &types.MsgAdjustDelegatedBalance{}) s.Require().ErrorContains(err, "host zone not found") - -} - -// ---------------------------------------------- -// MsgUpdateInnerRedemptionRateBounds -// ---------------------------------------------- - -func (s *KeeperTestSuite) TestUpdateInnerRedemptionRateBounds() { - adminAddress, ok := apptesting.GetAdminAddress() - s.Require().True(ok) - - // Register a host zone - zone := types.HostZone{ - ChainId: HostChainId, - // Upper bound 1.5 - MaxRedemptionRate: sdk.NewDec(3).Quo(sdk.NewDec(2)), - // Lower bound 0.9 - MinRedemptionRate: sdk.NewDec(9).Quo(sdk.NewDec(10)), - } - - s.App.StaketiaKeeper.SetHostZone(s.Ctx, zone) - // we're halting the zone to test that the tx works even when the host zone is halted - s.App.StaketiaKeeper.HaltZone(s.Ctx) - - initialMsg := types.MsgUpdateInnerRedemptionRateBounds{ - Creator: adminAddress, - MinInnerRedemptionRate: sdk.NewDec(90).Quo(sdk.NewDec(100)), - MaxInnerRedemptionRate: sdk.NewDec(105).Quo(sdk.NewDec(100)), - } - - updateMsg := types.MsgUpdateInnerRedemptionRateBounds{ - Creator: adminAddress, - MinInnerRedemptionRate: sdk.NewDec(95).Quo(sdk.NewDec(100)), - MaxInnerRedemptionRate: sdk.NewDec(11).Quo(sdk.NewDec(10)), - } - - invalidMsg := types.MsgUpdateInnerRedemptionRateBounds{ - Creator: adminAddress, - MinInnerRedemptionRate: sdk.NewDec(0), - MaxInnerRedemptionRate: sdk.NewDec(2), - } - - nonAdminMsg := types.MsgUpdateInnerRedemptionRateBounds{ - Creator: "non-admin", - MinInnerRedemptionRate: sdk.NewDec(0), - MaxInnerRedemptionRate: sdk.NewDec(2), - } - - // Set the inner bounds on the host zone for the first time - _, err := s.GetMsgServer().UpdateInnerRedemptionRateBounds(s.Ctx, &initialMsg) - s.Require().NoError(err, "should not throw an error") - - // Confirm the inner bounds were set - zone = s.MustGetHostZone() - s.Require().Equal(initialMsg.MinInnerRedemptionRate, zone.MinInnerRedemptionRate, "min inner redemption rate should be set") - s.Require().Equal(initialMsg.MaxInnerRedemptionRate, zone.MaxInnerRedemptionRate, "max inner redemption rate should be set") - - // Update the inner bounds on the host zone - _, err = s.GetMsgServer().UpdateInnerRedemptionRateBounds(s.Ctx, &updateMsg) - s.Require().NoError(err, "should not throw an error") - - // Confirm the inner bounds were set - zone = s.MustGetHostZone() - s.Require().Equal(updateMsg.MinInnerRedemptionRate, zone.MinInnerRedemptionRate, "min inner redemption rate should be set") - s.Require().Equal(updateMsg.MaxInnerRedemptionRate, zone.MaxInnerRedemptionRate, "max inner redemption rate should be set") - - // Set the inner bounds on the host zone for the first time - _, err = s.GetMsgServer().UpdateInnerRedemptionRateBounds(s.Ctx, &invalidMsg) - s.Require().ErrorContains(err, "invalid host zone redemption rate inner bounds") - - // Attempt to update bounds with a non-admin address, it should fail - _, err = s.GetMsgServer().UpdateInnerRedemptionRateBounds(s.Ctx, &nonAdminMsg) - s.Require().ErrorContains(err, "signer is not an admin") -} - -// ---------------------------------------------- -// MsgResumeHostZone -// ---------------------------------------------- - -// Test cases -// - Zone is not halted -// - Zone is halted - unhalt it -func (s *KeeperTestSuite) TestResumeHostZone() { - // TODO [sttia]: verify denom blacklisting removal works - - adminAddress, ok := apptesting.GetAdminAddress() - s.Require().True(ok) - - zone := types.HostZone{ - ChainId: HostChainId, - RedemptionRate: sdk.NewDec(1), - Halted: false, - NativeTokenDenom: HostNativeDenom, - } - s.App.StaketiaKeeper.SetHostZone(s.Ctx, zone) - - msg := types.MsgResumeHostZone{ - Creator: adminAddress, - } - - // TEST 1: Zone is not halted - // Try to unhalt the unhalted zone - _, err := s.GetMsgServer().ResumeHostZone(s.Ctx, &msg) - s.Require().ErrorContains(err, "zone is not halted") - - // Verify the denom is not in the blacklist - blacklist := s.App.RatelimitKeeper.GetAllBlacklistedDenoms(s.Ctx) - s.Require().NotContains(blacklist, StDenom, "denom should not be blacklisted") - - // Confirm the zone is not halted - zone, err = s.App.StaketiaKeeper.GetHostZone(s.Ctx) - s.Require().NoError(err, "should not throw an error") - s.Require().False(zone.Halted, "zone should not be halted") - - // TEST 2: Zone is halted - // Halt the zone - s.App.StaketiaKeeper.HaltZone(s.Ctx) - - // Verify the denom is in the blacklist - blacklist = s.App.RatelimitKeeper.GetAllBlacklistedDenoms(s.Ctx) - s.Require().Contains(blacklist, StDenom, "denom should be blacklisted") - - // Try to unhalt the halted zone - _, err = s.GetMsgServer().ResumeHostZone(s.Ctx, &msg) - s.Require().NoError(err, "should not throw an error") - - // Confirm the zone is not halted - zone, err = s.App.StaketiaKeeper.GetHostZone(s.Ctx) - s.Require().NoError(err, "should not throw an error") - s.Require().False(zone.Halted, "zone should not be halted") - - // Verify the denom is not in the blacklist - blacklist = s.App.RatelimitKeeper.GetAllBlacklistedDenoms(s.Ctx) - s.Require().NotContains(blacklist, StDenom, "denom should not be blacklisted") - - // Attempt to resume with a non-admin address, it should fail - _, err = s.GetMsgServer().ResumeHostZone(s.Ctx, &types.MsgResumeHostZone{ - Creator: "non-admin", - }) - s.Require().ErrorContains(err, "signer is not an admin") -} - -// ---------------------------------------------- -// MsgRefreshRedemptionRate -// ---------------------------------------------- - -func (s *KeeperTestSuite) TestRefreshRedemptionRate() { - safeAddress := "safe" - depositAddress := s.TestAccs[0] - redemptionAddress := s.TestAccs[1] - - // Create host zone with initial redemption rate of 1 - // There will be 1000 delegated tokens, and 500 stTokens - // implying an updated redemption rate of 2 - initialRedemptionRate := sdk.OneDec() - expectedRedemptionRate := sdk.NewDec(2) - - s.App.StaketiaKeeper.SetHostZone(s.Ctx, types.HostZone{ - DelegatedBalance: sdkmath.NewInt(1000), - RedemptionRate: initialRedemptionRate, - NativeTokenDenom: HostNativeDenom, - NativeTokenIbcDenom: HostIBCDenom, - SafeAddressOnStride: safeAddress, - DepositAddress: depositAddress.String(), - }) - - // Mint 500 stTokens (implying a redemption rate of 2) - s.FundAccount(redemptionAddress, sdk.NewCoin(StDenom, sdkmath.NewInt(500))) - - // Attempt to refresh the rate with a non-safe address, it should fail - _, err := s.GetMsgServer().RefreshRedemptionRate(s.Ctx, &types.MsgRefreshRedemptionRate{ - Creator: "non-admin", - }) - s.Require().ErrorContains(err, "signer is not an admin") - - // Attempt to refresh the rate with the safe address, it should succeed - _, err = s.GetMsgServer().RefreshRedemptionRate(s.Ctx, &types.MsgRefreshRedemptionRate{ - Creator: safeAddress, - }) - s.Require().NoError(err, "no error expected when using safe address") - - // Confirm the redemption rate was updated - hostZone := s.MustGetHostZone() - s.Require().Equal(expectedRedemptionRate, hostZone.RedemptionRate) } // ---------------------------------------------- diff --git a/x/staketia/keeper/redemption_rate.go b/x/staketia/keeper/redemption_rate.go index 33100c4ade..57d3f3eac1 100644 --- a/x/staketia/keeper/redemption_rate.go +++ b/x/staketia/keeper/redemption_rate.go @@ -1,101 +1,20 @@ package keeper import ( - "encoding/json" - "errors" - "fmt" - - errorsmod "cosmossdk.io/errors" - sdkmath "cosmossdk.io/math" sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/Stride-Labs/stride/v24/utils" - icaoracletypes "github.com/Stride-Labs/stride/v24/x/icaoracle/types" "github.com/Stride-Labs/stride/v24/x/staketia/types" ) -// Updates the redemption rate for each host zone -// At a high level, the redemption rate is equal to the amount of native tokens locked divided by the stTokens in existence. -// The equation is broken down further into the following sub-components: -// -// Native Tokens Locked: -// 1. Deposit Account Balance: tokens deposited from liquid stakes, that are still living on Stride -// 2. Undelegated Balance: tokens that are ready to be staked -// (they're either currently in the delegation account or currently being transferred there) -// 3. Delegated Balance: Delegations on the host zone -// -// StToken Amount: -// 1. Total Supply of the stToken -// -// Redemption Rate = (Deposit Account Balance + Undelegated Balance + Delegated Balance) / (stToken Supply) -// -// Note: Reinvested tokens are sent to the deposit account and are automatically included in this formula -func (k Keeper) UpdateRedemptionRate(ctx sdk.Context) error { - k.Logger(ctx).Info(utils.LogWithHostZone(types.CelestiaChainId, "Updating redemption rate")) - - hostZone, err := k.GetHostZone(ctx) - if err != nil { - return err - } - - // Get the number of stTokens from the supply - stTokenSupply := k.bankKeeper.GetSupply(ctx, utils.StAssetDenomFromHostZoneDenom(hostZone.NativeTokenDenom)).Amount - if stTokenSupply.IsZero() { - k.Logger(ctx).Info(utils.LogWithHostZone(hostZone.ChainId, - "No st%s in circulation - redemption rate is unchanged", hostZone.NativeTokenDenom)) - return nil - } - - // Get the balance of the deposit address - depositAddress, err := sdk.AccAddressFromBech32(hostZone.DepositAddress) - if err != nil { - return errorsmod.Wrapf(err, "invalid deposit address") - } - depositAccountBalance := k.bankKeeper.GetBalance(ctx, depositAddress, hostZone.NativeTokenIbcDenom) - - // Then add that to the sum of the delegation records to get the undelegated balance - // Delegation records are only created once the tokens leave the deposit address - // and the record is deleted once the tokens are delegated - undelegatedBalance := sdkmath.ZeroInt() - for _, delegationRecord := range k.GetAllActiveDelegationRecords(ctx) { - undelegatedBalance = undelegatedBalance.Add(delegationRecord.NativeAmount) - } - - // Finally, calculated the redemption rate as the native tokens locked divided by the stTokens - nativeTokensLocked := depositAccountBalance.Amount.Add(undelegatedBalance).Add(hostZone.DelegatedBalance) - if !nativeTokensLocked.IsPositive() { - return errors.New("Non-zero stToken supply, yet the zero delegated and undelegated balance") - } - redemptionRate := sdk.NewDecFromInt(nativeTokensLocked).Quo(sdk.NewDecFromInt(stTokenSupply)) - - // Set the old and update redemption rate on the host - hostZone.LastRedemptionRate = hostZone.RedemptionRate - hostZone.RedemptionRate = redemptionRate - k.SetHostZone(ctx, hostZone) - - k.Logger(ctx).Info(utils.LogWithHostZone(types.CelestiaChainId, "Redemption rate updated from %v to %v", - hostZone.LastRedemptionRate, hostZone.RedemptionRate)) - k.Logger(ctx).Info(utils.LogWithHostZone(types.CelestiaChainId, - "Deposit Account Balance: %v, Undelegated Balance: %v, Delegated Balance: %v, StToken Supply: %v", - depositAccountBalance.Amount, undelegatedBalance, hostZone.DelegatedBalance, stTokenSupply)) - - return nil -} - // Checks whether the redemption rate has exceeded the inner or outer safety bounds // and returns an error if so func (k Keeper) CheckRedemptionRateExceedsBounds(ctx sdk.Context) error { - hostZone, err := k.GetHostZone(ctx) - if err != nil { - return err + hostZone, found := k.stakeibcKeeper.GetHostZone(ctx, types.CelestiaChainId) + if !found { + return types.ErrHostZoneNotFound } redemptionRate := hostZone.RedemptionRate - // Validate the safety bounds (e.g. that the inner is inside the outer) - if err := hostZone.ValidateRedemptionRateBoundsInitalized(); err != nil { - return err - } - // Check if the redemption rate is outside the outer bounds if redemptionRate.LT(hostZone.MinRedemptionRate) || redemptionRate.GT(hostZone.MaxRedemptionRate) { return types.ErrRedemptionRateOutsideSafetyBounds.Wrapf("redemption rate outside outer safety bounds") @@ -108,32 +27,3 @@ func (k Keeper) CheckRedemptionRateExceedsBounds(ctx sdk.Context) error { return nil } - -// Pushes a redemption rate update to the ICA oracle -func (k Keeper) PostRedemptionRateToOracles(ctx sdk.Context) error { - if err := k.CheckRedemptionRateExceedsBounds(ctx); err != nil { - return errorsmod.Wrapf(err, "preventing oracle update since redemption rate exceeded bounds") - } - - hostZone, err := k.GetHostZone(ctx) - if err != nil { - return err - } - redemptionRate := hostZone.RedemptionRate - - stDenom := utils.StAssetDenomFromHostZoneDenom(hostZone.NativeTokenDenom) - attributes, err := json.Marshal(icaoracletypes.RedemptionRateAttributes{ - SttokenDenom: stDenom, - }) - if err != nil { - return err - } - - // Metric Key is of format: {stToken}_redemption_rate - metricKey := fmt.Sprintf("%s_%s", stDenom, icaoracletypes.MetricType_RedemptionRate) - metricValue := redemptionRate.String() - metricType := icaoracletypes.MetricType_RedemptionRate - k.icaOracleKeeper.QueueMetricUpdate(ctx, metricKey, metricValue, metricType, string(attributes)) - - return nil -} diff --git a/x/staketia/keeper/redemption_rate_test.go b/x/staketia/keeper/redemption_rate_test.go index 125c23c7a8..6c8607a539 100644 --- a/x/staketia/keeper/redemption_rate_test.go +++ b/x/staketia/keeper/redemption_rate_test.go @@ -1,171 +1,21 @@ package keeper_test import ( - "fmt" - - sdkmath "cosmossdk.io/math" sdk "github.com/cosmos/cosmos-sdk/types" + stakeibctypes "github.com/Stride-Labs/stride/v24/x/stakeibc/types" "github.com/Stride-Labs/stride/v24/x/staketia/types" ) -func (s *KeeperTestSuite) TestUpdateRedemptionRate() { - depositAddress := s.TestAccs[0] - - testCases := []struct { - expectedRedemptionRate sdk.Dec - depositBalance sdkmath.Int - delegatedBalance sdkmath.Int - stTokenSupply sdkmath.Int - delegationRecords []types.DelegationRecord - }{ - { - // Deposit: 250, Undelegated: 500, Delegated: 250, StTokens: 1000 - // (250 + 500 + 250 / 1000) = 1000 / 1000 = 1.0 - expectedRedemptionRate: sdk.MustNewDecFromStr("1.0"), - depositBalance: sdkmath.NewInt(250), - delegatedBalance: sdkmath.NewInt(250), - delegationRecords: []types.DelegationRecord{ - {Id: 1, NativeAmount: sdkmath.NewInt(250), Status: types.TRANSFER_IN_PROGRESS}, - {Id: 2, NativeAmount: sdkmath.NewInt(250), Status: types.DELEGATION_QUEUE}, - }, - stTokenSupply: sdkmath.NewInt(1000), - }, - { - // Deposit: 500, Undelegated: 500, Delegated: 250, StTokens: 1000 - // (500 + 500 + 250 / 1000) = 1250 / 1000 = 1.25 - expectedRedemptionRate: sdk.MustNewDecFromStr("1.25"), - depositBalance: sdkmath.NewInt(500), - delegatedBalance: sdkmath.NewInt(250), - delegationRecords: []types.DelegationRecord{ - {Id: 1, NativeAmount: sdkmath.NewInt(250), Status: types.TRANSFER_IN_PROGRESS}, - {Id: 2, NativeAmount: sdkmath.NewInt(250), Status: types.DELEGATION_QUEUE}, - }, - stTokenSupply: sdkmath.NewInt(1000), - }, - { - // Deposit: 250, Undelegated: 500, Delegated: 500, StTokens: 1000 - // (500 + 500 + 250 / 1000) = 1250 / 1000 = 1.250 - expectedRedemptionRate: sdk.MustNewDecFromStr("1.25"), - depositBalance: sdkmath.NewInt(250), - delegatedBalance: sdkmath.NewInt(500), - delegationRecords: []types.DelegationRecord{ - {Id: 2, NativeAmount: sdkmath.NewInt(250), Status: types.TRANSFER_IN_PROGRESS}, - {Id: 3, NativeAmount: sdkmath.NewInt(250), Status: types.DELEGATION_QUEUE}, - }, - stTokenSupply: sdkmath.NewInt(1000), - }, - { - // Deposit: 250, Undelegated: 1000, Delegated: 250, StTokens: 1000 - // (250 + 1000 + 250 / 1000) = 1500 / 1000 = 1.5 - expectedRedemptionRate: sdk.MustNewDecFromStr("1.5"), - depositBalance: sdkmath.NewInt(250), - delegatedBalance: sdkmath.NewInt(250), - delegationRecords: []types.DelegationRecord{ - {Id: 1, NativeAmount: sdkmath.NewInt(250), Status: types.TRANSFER_IN_PROGRESS}, - {Id: 2, NativeAmount: sdkmath.NewInt(250), Status: types.DELEGATION_QUEUE}, - {Id: 4, NativeAmount: sdkmath.NewInt(250), Status: types.TRANSFER_IN_PROGRESS}, - {Id: 6, NativeAmount: sdkmath.NewInt(250), Status: types.DELEGATION_QUEUE}, - }, - stTokenSupply: sdkmath.NewInt(1000), - }, - { - // Deposit: 250, Undelegated: 500, Delegated: 250, StTokens: 2000 - // (250 + 500 + 250 / 2000) = 1000 / 2000 = 0.5 - expectedRedemptionRate: sdk.MustNewDecFromStr("0.5"), - depositBalance: sdkmath.NewInt(250), - delegatedBalance: sdkmath.NewInt(250), - delegationRecords: []types.DelegationRecord{ - {Id: 1, NativeAmount: sdkmath.NewInt(250), Status: types.TRANSFER_IN_PROGRESS}, - {Id: 2, NativeAmount: sdkmath.NewInt(250), Status: types.DELEGATION_QUEUE}, - }, - stTokenSupply: sdkmath.NewInt(2000), - }, - } - - for i, tc := range testCases { - s.Run(fmt.Sprintf("test-%d", i), func() { - s.SetupTest() // reset state - - // Fund the deposit balance - s.FundAccount(depositAddress, sdk.NewCoin(HostIBCDenom, tc.depositBalance)) - - // Create the host zone with the delegated balance and deposit address - initialRedemptionRate := sdk.MustNewDecFromStr("0.999") - s.App.StaketiaKeeper.SetHostZone(s.Ctx, types.HostZone{ - NativeTokenDenom: HostNativeDenom, - NativeTokenIbcDenom: HostIBCDenom, - DepositAddress: depositAddress.String(), - DelegatedBalance: tc.delegatedBalance, - RedemptionRate: initialRedemptionRate, - }) - - // Set each delegation record - for _, delegationRecord := range tc.delegationRecords { - s.App.StaketiaKeeper.SetDelegationRecord(s.Ctx, delegationRecord) - } - - // Add some archive delegation records that should be excluded - // We'll create these by first creating normal records and then removing them - for i := 0; i <= 5; i++ { - id := uint64(i * 1000) - s.App.StaketiaKeeper.SetArchivedDelegationRecord(s.Ctx, types.DelegationRecord{Id: id}) - } - - // Mint sttokens for the supply (fund account calls mint) - s.FundAccount(s.TestAccs[1], sdk.NewCoin(StDenom, tc.stTokenSupply)) - - // Update the redemption rate and check that it matches - err := s.App.StaketiaKeeper.UpdateRedemptionRate(s.Ctx) - s.Require().NoError(err, "no error expected when calculating redemption rate") - - hostZone := s.MustGetHostZone() - s.Require().Equal(tc.expectedRedemptionRate, hostZone.RedemptionRate, "redemption rate") - - // Check that the last redemption rate was set - s.Require().Equal(initialRedemptionRate, hostZone.LastRedemptionRate, "redemption rate") - }) - - } -} - -func (s *KeeperTestSuite) TestUpdateRedemptionRate_NoTokens() { - depositAddress := s.TestAccs[0] - - // Create the host zone with no delegated balance - s.App.StaketiaKeeper.SetHostZone(s.Ctx, types.HostZone{ - NativeTokenDenom: HostNativeDenom, - NativeTokenIbcDenom: HostIBCDenom, - DepositAddress: depositAddress.String(), - DelegatedBalance: sdkmath.ZeroInt(), - RedemptionRate: sdk.OneDec(), - }) - - // Check that the update funtion returns nil, since there are no stTokens - err := s.App.StaketiaKeeper.UpdateRedemptionRate(s.Ctx) - s.Require().NoError(err, "no error when there are no stTokens") - - // Check that the redemption rate was not updated - hostZone := s.MustGetHostZone() - s.Require().Equal(sdk.OneDec(), hostZone.RedemptionRate, "redemption rate should not have been updated") - - // Mint stTokens - s.FundAccount(s.TestAccs[1], sdk.NewCoin(StDenom, sdkmath.NewInt(1000))) - - // Try to update again, now it should error since there's stTokens but no native tokens - err = s.App.StaketiaKeeper.UpdateRedemptionRate(s.Ctx) - s.Require().ErrorContains(err, "Non-zero stToken supply, yet the zero delegated and undelegated balance") -} - func (s *KeeperTestSuite) TestCheckRedemptionRateExceedsBounds() { testCases := []struct { name string - hostZone types.HostZone + hostZone stakeibctypes.HostZone exceedsBounds bool }{ { name: "valid bounds", - hostZone: types.HostZone{ + hostZone: stakeibctypes.HostZone{ MinRedemptionRate: sdk.MustNewDecFromStr("0.8"), MinInnerRedemptionRate: sdk.MustNewDecFromStr("0.9"), RedemptionRate: sdk.MustNewDecFromStr("1.0"), // <-- @@ -176,7 +26,7 @@ func (s *KeeperTestSuite) TestCheckRedemptionRateExceedsBounds() { }, { name: "outside min inner", - hostZone: types.HostZone{ + hostZone: stakeibctypes.HostZone{ MinRedemptionRate: sdk.MustNewDecFromStr("0.8"), RedemptionRate: sdk.MustNewDecFromStr("0.9"), // <-- MinInnerRedemptionRate: sdk.MustNewDecFromStr("1.0"), @@ -187,7 +37,7 @@ func (s *KeeperTestSuite) TestCheckRedemptionRateExceedsBounds() { }, { name: "outside max inner", - hostZone: types.HostZone{ + hostZone: stakeibctypes.HostZone{ MinRedemptionRate: sdk.MustNewDecFromStr("0.8"), MinInnerRedemptionRate: sdk.MustNewDecFromStr("0.9"), MaxInnerRedemptionRate: sdk.MustNewDecFromStr("1.0"), @@ -198,7 +48,7 @@ func (s *KeeperTestSuite) TestCheckRedemptionRateExceedsBounds() { }, { name: "outside min outer", - hostZone: types.HostZone{ + hostZone: stakeibctypes.HostZone{ RedemptionRate: sdk.MustNewDecFromStr("0.8"), // <-- MinRedemptionRate: sdk.MustNewDecFromStr("0.9"), MinInnerRedemptionRate: sdk.MustNewDecFromStr("1.0"), @@ -209,7 +59,7 @@ func (s *KeeperTestSuite) TestCheckRedemptionRateExceedsBounds() { }, { name: "outside max outer", - hostZone: types.HostZone{ + hostZone: stakeibctypes.HostZone{ MinRedemptionRate: sdk.MustNewDecFromStr("0.8"), MinInnerRedemptionRate: sdk.MustNewDecFromStr("0.9"), MaxInnerRedemptionRate: sdk.MustNewDecFromStr("1.0"), @@ -222,7 +72,10 @@ func (s *KeeperTestSuite) TestCheckRedemptionRateExceedsBounds() { for _, tc := range testCases { s.Run(tc.name, func() { - s.App.StaketiaKeeper.SetHostZone(s.Ctx, tc.hostZone) + hostZone := tc.hostZone + hostZone.ChainId = types.CelestiaChainId + s.App.StakeibcKeeper.SetHostZone(s.Ctx, hostZone) + err := s.App.StaketiaKeeper.CheckRedemptionRateExceedsBounds(s.Ctx) if tc.exceedsBounds { s.Require().ErrorIs(err, types.ErrRedemptionRateOutsideSafetyBounds) diff --git a/x/staketia/keeper/unbonding.go b/x/staketia/keeper/unbonding.go index 5b6529eb93..d00a648c7b 100644 --- a/x/staketia/keeper/unbonding.go +++ b/x/staketia/keeper/unbonding.go @@ -10,21 +10,38 @@ import ( sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" "github.com/Stride-Labs/stride/v24/utils" + stakeibctypes "github.com/Stride-Labs/stride/v24/x/stakeibc/types" "github.com/Stride-Labs/stride/v24/x/staketia/types" ) // Takes custody of staked tokens in an escrow account, updates the current // accumulating UnbondingRecord with the amount taken, and creates or updates // the RedemptionRecord for this user -func (k Keeper) RedeemStake(ctx sdk.Context, redeemer string, stTokenAmount sdkmath.Int) (nativeToken sdk.Coin, err error) { +func (k Keeper) RedeemStake( + ctx sdk.Context, + redeemer string, + receiver string, + stTokenAmount sdkmath.Int, +) (nativeToken sdk.Coin, err error) { // Validate Basic already has ensured redeemer is legal address, stTokenAmount is above min threshold - // Check HostZone exists, has legal redemption address for escrow, is not halted, has RR in bounds + // Check HostZone exists, and that the stakeibc host zone is not halted hostZone, err := k.GetUnhaltedHostZone(ctx) if err != nil { return nativeToken, err } + stakeibcHostZone, err := k.stakeibcKeeper.GetActiveHostZone(ctx, types.CelestiaChainId) + if err != nil { + return nativeToken, err + } + + // If the remaining delegated balance for staketia is 0, that means we've undelegated + // all the stake in the MS account and the redemptions should be switched over to stakeibc + if hostZone.RemainingDelegatedBalance.LTE(sdkmath.ZeroInt()) { + return nativeToken, types.ErrRedemptionsDisabled + } + // Check that the redemption address exists as the escrow account escrowAccount, err := sdk.AccAddressFromBech32(hostZone.RedemptionAddress) if err != nil { return nativeToken, errorsmod.Wrapf(err, "could not bech32 decode redemption address %s on stride", hostZone.RedemptionAddress) @@ -56,12 +73,45 @@ func (k Keeper) RedeemStake(ctx sdk.Context, redeemer string, stTokenAmount sdkm // Estimate a placeholder native amount with current RedemptionRate // this estimate will be updated when the Undelegation record is finalized - nativeAmount := sdk.NewDecFromInt(stTokenAmount).Mul(hostZone.RedemptionRate).TruncateInt() - if nativeAmount.GT(hostZone.DelegatedBalance) { + nativeAmount := sdk.NewDecFromInt(stTokenAmount).Mul(stakeibcHostZone.RedemptionRate).TruncateInt() + + // When checking if there's enough delegated TIA to handle the request, + // use the value from stakeibc instead of staketia + if nativeAmount.GT(stakeibcHostZone.TotalDelegations) { return nativeToken, errorsmod.Wrapf(types.ErrUnbondAmountToLarge, - "cannot unstake an amount g.t. total staked balance: %v > %v", nativeAmount, hostZone.DelegatedBalance) + "cannot unstake an amount g.t. total staked balance: %v > %v", nativeAmount, stakeibcHostZone.TotalDelegations) + } + + // If the requested unbonding amount is greater than or equal to what's in the multisig account, + // this will be the last staketia redemption and we should enable redemptions in stakeibc + if nativeAmount.GTE(hostZone.RemainingDelegatedBalance) { + if err := k.stakeibcKeeper.EnableRedemptions(ctx, types.CelestiaChainId); err != nil { + return nativeToken, errorsmod.Wrapf(err, "unable to enable redemptions") + } + } + + // If the requested unbonding is greater than what's in the multisig account + // we need to handle the spillover in stakeibc + // This will return the remaining amount back to be processed in staketia + if nativeAmount.GT(hostZone.RemainingDelegatedBalance) { + nativeAmount, stTokenAmount, err = k.HandleRedemptionSpillover( + ctx, + redeemer, + receiver, + nativeAmount, + stTokenAmount, + hostZone.RemainingDelegatedBalance, + stakeibcHostZone.RedemptionRate, + ) + if err != nil { + return nativeToken, err + } } + // Decrement the remaining delegation - if there was spillover, this will get set to 0 + hostZone.RemainingDelegatedBalance = hostZone.RemainingDelegatedBalance.Sub(nativeAmount) + k.SetHostZone(ctx, hostZone) + // Update the accumulating UnbondingRecord with the undelegation amounts accUnbondingRecord.StTokenAmount = accUnbondingRecord.StTokenAmount.Add(stTokenAmount) accUnbondingRecord.NativeAmount = accUnbondingRecord.NativeAmount.Add(nativeAmount) @@ -98,17 +148,49 @@ func (k Keeper) RedeemStake(ctx sdk.Context, redeemer string, stTokenAmount sdkm return nativeToken, nil } +// Calls redeem stake for any requested redemption amount that exceeds what's in the staketia account +// Returns the updated native and stTokens amounts that should be used in staketia +func (k Keeper) HandleRedemptionSpillover( + ctx sdk.Context, + redeemer string, + receiver string, + requestedNativeAmount sdkmath.Int, + requestedStTokenAmount sdkmath.Int, + remainingDelegatedBalance sdkmath.Int, + redemptionRate sdk.Dec, +) (staketiaNativeAmount, staketiaStTokenAmount sdkmath.Int, err error) { + // Converts the spillover amount so that it's denominated in stTokens + stakeibcNativeAmount := requestedNativeAmount.Sub(remainingDelegatedBalance) + stakeibcStTokenAmount := sdk.NewDecFromInt(stakeibcNativeAmount).Quo(redemptionRate).TruncateInt() + + // Call stakeibc's redeem stake for the excess + stakeibcRedeemMessage := stakeibctypes.MsgRedeemStake{ + Creator: redeemer, + Amount: stakeibcStTokenAmount, + HostZone: types.CelestiaChainId, + Receiver: receiver, + } + if _, err = k.stakeibcKeeper.RedeemStake(ctx, &stakeibcRedeemMessage); err != nil { + return sdkmath.ZeroInt(), sdkmath.ZeroInt(), errorsmod.Wrapf(err, "unable to execute stakeibc redeem stake") + } + + // Return the updated staketia portion back to the staketia redeem stake + staketiaNativeAmount = requestedNativeAmount.Sub(stakeibcNativeAmount) + staketiaStTokenAmount = requestedStTokenAmount.Sub(stakeibcStTokenAmount) + return staketiaNativeAmount, staketiaStTokenAmount, nil +} + // Freezes the ACCUMULATING record by changing the status to UNBONDING_QUEUE // and updating the native token amounts on the unbonding and redemption records func (k Keeper) PrepareUndelegation(ctx sdk.Context, epochNumber uint64) error { k.Logger(ctx).Info(utils.LogWithHostZone(types.CelestiaChainId, "Preparing undelegation for epoch %d", epochNumber)) // Get the redemption record from the host zone (to calculate the native tokens) - hostZone, err := k.GetUnhaltedHostZone(ctx) + stakeibcHostZone, err := k.stakeibcKeeper.GetActiveHostZone(ctx, types.CelestiaChainId) if err != nil { return err } - redemptionRate := hostZone.RedemptionRate + redemptionRate := stakeibcHostZone.RedemptionRate // Get the one accumulating record that has the redemptions for the past epoch unbondingRecord, err := k.GetAccumulatingUnbondingRecord(ctx) @@ -176,19 +258,21 @@ func (k Keeper) ConfirmUndelegation(ctx sdk.Context, recordId uint64, txHash str } // Note: we're intentionally not checking that the host zone is halted, because we still want to process this tx in that case - hostZone, err := k.GetHostZone(ctx) + staketiaHostZone, err := k.GetHostZone(ctx) + if err != nil { + return err + } + stakeibcHostZone, err := k.stakeibcKeeper.GetActiveHostZone(ctx, types.CelestiaChainId) if err != nil { return err } // sanity check: store down the stToken supply and DelegatedBalance for checking against after burn - stDenom := utils.StAssetDenomFromHostZoneDenom(hostZone.NativeTokenDenom) - stTokenSupplyBefore := k.bankKeeper.GetSupply(ctx, stDenom).Amount - delegatedBalanceBefore := hostZone.DelegatedBalance + stDenom := utils.StAssetDenomFromHostZoneDenom(staketiaHostZone.NativeTokenDenom) // update the record's txhash, status, and unbonding completion time - unbondingLength := time.Duration(hostZone.UnbondingPeriodSeconds) * time.Second // 21 days - unbondingCompletionTime := uint64(ctx.BlockTime().Add(unbondingLength).Unix()) // now + 21 days + unbondingLength := time.Duration(staketiaHostZone.UnbondingPeriodSeconds) * time.Second // 21 days + unbondingCompletionTime := uint64(ctx.BlockTime().Add(unbondingLength).Unix()) // now + 21 days record.UndelegationTxHash = txHash record.Status = types.UNBONDING_IN_PROGRESS @@ -197,26 +281,21 @@ func (k Keeper) ConfirmUndelegation(ctx sdk.Context, recordId uint64, txHash str // update host zone struct's delegated balance amountAddedToDelegation := record.NativeAmount - newDelegatedBalance := hostZone.DelegatedBalance.Sub(amountAddedToDelegation) + newDelegatedBalance := stakeibcHostZone.TotalDelegations.Sub(amountAddedToDelegation) // sanity check: if the new balance is negative, throw an error if newDelegatedBalance.IsNegative() { return errorsmod.Wrapf(types.ErrNegativeNotAllowed, "host zone's delegated balance would be negative after undelegation") } - hostZone.DelegatedBalance = newDelegatedBalance - k.SetHostZone(ctx, hostZone) + stakeibcHostZone.TotalDelegations = newDelegatedBalance + k.stakeibcKeeper.SetHostZone(ctx, stakeibcHostZone) // burn the corresponding stTokens from the redemptionAddress stTokensToBurn := sdk.NewCoins(sdk.NewCoin(stDenom, record.StTokenAmount)) - if err := k.BurnRedeemedStTokens(ctx, stTokensToBurn, hostZone.RedemptionAddress); err != nil { + if err := k.BurnRedeemedStTokens(ctx, stTokensToBurn, staketiaHostZone.RedemptionAddress); err != nil { return errorsmod.Wrapf(err, "unable to burn stTokens in ConfirmUndelegation") } - // sanity check: check that (DelegatedBalance increment / stToken supply decrement) is within outer bounds - if err := k.VerifyImpliedRedemptionRateFromUnbonding(ctx, stTokenSupplyBefore, delegatedBalanceBefore); err != nil { - return errorsmod.Wrap(err, "ratio of delegation change to burned tokens exceeds redemption rate bounds") - } - EmitSuccessfulConfirmUndelegationEvent(ctx, recordId, record.NativeAmount, txHash, sender) return nil } @@ -245,37 +324,6 @@ func (k Keeper) BurnRedeemedStTokens(ctx sdk.Context, stTokensToBurn sdk.Coins, return nil } -// Sanity check helper for checking diffs on delegated balance and stToken supply are within outer RR bounds -func (k Keeper) VerifyImpliedRedemptionRateFromUnbonding(ctx sdk.Context, stTokenSupplyBefore sdkmath.Int, delegatedBalanceBefore sdkmath.Int) error { - hostZoneAfter, err := k.GetHostZone(ctx) - if err != nil { - return types.ErrHostZoneNotFound - } - stDenom := utils.StAssetDenomFromHostZoneDenom(hostZoneAfter.NativeTokenDenom) - - // grab the delegated balance and token supply after the burn - delegatedBalanceAfter := hostZoneAfter.DelegatedBalance - stTokenSupplyAfter := k.bankKeeper.GetSupply(ctx, stDenom).Amount - - // calculate the delta for both the delegated balance and stToken burn - delegatedBalanceDecremented := delegatedBalanceBefore.Sub(delegatedBalanceAfter) - stTokenSupplyBurned := stTokenSupplyBefore.Sub(stTokenSupplyAfter) - - // It shouldn't be possible for this to be zero, but this will prevent a division by zero error - if stTokenSupplyBurned.IsZero() { - return types.ErrDivisionByZero - } - - // calculate the ratio of delegated balance change to stToken burn - it should be close to the redemption rate - ratio := sdk.NewDecFromInt(delegatedBalanceDecremented).Quo(sdk.NewDecFromInt(stTokenSupplyBurned)) - - // check ratio against bounds - if ratio.LT(hostZoneAfter.MinRedemptionRate) || ratio.GT(hostZoneAfter.MaxRedemptionRate) { - return types.ErrRedemptionRateOutsideSafetyBounds - } - return nil -} - // Checks for any unbonding records that have finished unbonding, // identified by having status UNBONDING_IN_PROGRESS and an // unbonding that's older than the current time. @@ -342,10 +390,15 @@ func (k Keeper) ConfirmUnbondedTokenSweep(ctx sdk.Context, recordId uint64, txHa func (k Keeper) DistributeClaims(ctx sdk.Context) error { // Get the claim address which will be the sender // The token denom will be the native host zone token in it's IBC form as it lives on stride + // We check the stakeibc host zone as well to confirm there's no halt hostZone, err := k.GetUnhaltedHostZone(ctx) if err != nil { return err } + _, err = k.stakeibcKeeper.GetActiveHostZone(ctx, types.CelestiaChainId) + if err != nil { + return err + } nativeTokenIbcDenom := hostZone.NativeTokenIbcDenom claimAddress, err := sdk.AccAddressFromBech32(hostZone.ClaimAddress) diff --git a/x/staketia/keeper/unbonding_test.go b/x/staketia/keeper/unbonding_test.go index a0e18ecbe8..4c5e2be7c4 100644 --- a/x/staketia/keeper/unbonding_test.go +++ b/x/staketia/keeper/unbonding_test.go @@ -9,6 +9,9 @@ import ( "github.com/Stride-Labs/stride/v24/app/apptesting" "github.com/Stride-Labs/stride/v24/utils" + epochtypes "github.com/Stride-Labs/stride/v24/x/epochs/types" + recordtypes "github.com/Stride-Labs/stride/v24/x/records/types" + stakeibctypes "github.com/Stride-Labs/stride/v24/x/stakeibc/types" "github.com/Stride-Labs/stride/v24/x/staketia/types" ) @@ -29,19 +32,23 @@ type RedeemStakeTestCase struct { userAccount Account hostZone *types.HostZone + stakeibcHostZone *stakeibctypes.HostZone accUnbondRecord *types.UnbondingRecord redemptionRecord *types.RedemptionRecord redeemMsg types.MsgRedeemStake - expectedUnbondingRecord *types.UnbondingRecord - expectedRedemptionRecord *types.RedemptionRecord - expectedErrorContains string + expectedUnbondingRecord *types.UnbondingRecord + expectedRedemptionRecord *types.RedemptionRecord + expectedStakeibcRedemptionAmount sdkmath.Int + expectedStakeibcRedemptionsEnabled bool + expectedErrorContains string } // Create the correct amounts in accounts, setup the records in store func (s *KeeperTestSuite) SetupTestRedeemStake( userAccount Account, hostZone *types.HostZone, + stakeibcHostZone *stakeibctypes.HostZone, accUnbondRecord *types.UnbondingRecord, redemptionRecord *types.RedemptionRecord, ) { @@ -52,6 +59,10 @@ func (s *KeeperTestSuite) SetupTestRedeemStake( s.App.StaketiaKeeper.SetHostZone(s.Ctx, *hostZone) } + if stakeibcHostZone != nil { + s.App.StakeibcKeeper.SetHostZone(s.Ctx, *stakeibcHostZone) + } + if accUnbondRecord != nil { s.App.StaketiaKeeper.SetUnbondingRecord(s.Ctx, *accUnbondRecord) } @@ -68,18 +79,39 @@ func (s *KeeperTestSuite) SetupTestRedeemStake( if redemptionRecord != nil { s.App.StaketiaKeeper.SetRedemptionRecord(s.Ctx, *redemptionRecord) } + + // Prepare stakeibc for a redemption + epochNumber := uint64(1) + s.App.StakeibcKeeper.SetEpochTracker(s.Ctx, stakeibctypes.EpochTracker{ + EpochIdentifier: epochtypes.DAY_EPOCH, + EpochNumber: epochNumber, + }) + + s.App.RecordsKeeper.SetEpochUnbondingRecord(s.Ctx, recordtypes.EpochUnbondingRecord{ + EpochNumber: epochNumber, + HostZoneUnbondings: []*recordtypes.HostZoneUnbonding{ + { + HostZoneId: types.CelestiaChainId, + StTokenAmount: sdkmath.ZeroInt(), + NativeTokenAmount: sdkmath.ZeroInt(), + }, + }, + }) } // Default values for key variables, different tests will change 1-2 fields for setup func (s *KeeperTestSuite) getDefaultTestInputs() ( *Account, *types.HostZone, + *stakeibctypes.HostZone, *types.UnbondingRecord, *types.RedemptionRecord, *types.MsgRedeemStake, ) { redeemerAccount := s.TestAccs[0] redemptionAccount := s.TestAccs[1] + receiverAddress := s.TestAccs[2].String() + depositAddress := s.TestAccs[3].String() defaultUserAccount := Account{ account: redeemerAccount, @@ -88,16 +120,23 @@ func (s *KeeperTestSuite) getDefaultTestInputs() ( } redemptionRate := sdk.MustNewDecFromStr("1.1") - defaultHostZone := types.HostZone{ - NativeTokenDenom: HostNativeDenom, - RedemptionAddress: redemptionAccount.String(), + defaultStaketiaHostZone := types.HostZone{ + NativeTokenDenom: HostNativeDenom, + RedemptionAddress: redemptionAccount.String(), + RemainingDelegatedBalance: sdkmath.NewInt(1_000_000_000), + Halted: false, + } + defaultStakeibcHostZone := stakeibctypes.HostZone{ + ChainId: types.CelestiaChainId, + HostDenom: HostNativeDenom, + Bech32Prefix: "stride", + DepositAddress: depositAddress, RedemptionRate: redemptionRate, MinRedemptionRate: redemptionRate.Sub(sdk.MustNewDecFromStr("0.2")), MinInnerRedemptionRate: redemptionRate.Sub(sdk.MustNewDecFromStr("0.1")), MaxInnerRedemptionRate: redemptionRate.Add(sdk.MustNewDecFromStr("0.1")), MaxRedemptionRate: redemptionRate.Add(sdk.MustNewDecFromStr("0.2")), - DelegatedBalance: sdkmath.NewInt(1_000_000_000), - Halted: false, + TotalDelegations: sdkmath.NewInt(1_000_000_000), } defaultAccUnbondingRecord := types.UnbondingRecord{ @@ -119,21 +158,32 @@ func (s *KeeperTestSuite) getDefaultTestInputs() ( defaultMsg := types.MsgRedeemStake{ Redeemer: redeemerAccount.String(), StTokenAmount: sdk.NewInt(1_000_000), + Receiver: receiverAddress, } - return &defaultUserAccount, &defaultHostZone, &defaultAccUnbondingRecord, - &defaultRedemptionRecord, &defaultMsg + return &defaultUserAccount, &defaultStaketiaHostZone, &defaultStakeibcHostZone, + &defaultAccUnbondingRecord, &defaultRedemptionRecord, &defaultMsg } func (s *KeeperTestSuite) TestRedeemStake() { - defaultUA, defaultHZ, defaultUR, defaultRR, defaultMsg := s.getDefaultTestInputs() + defaultUA, defaultMsHZ, defaultIcaHZ, defaultUR, defaultRR, defaultMsg := s.getDefaultTestInputs() testCases := []RedeemStakeTestCase{ { testName: "[Error] Can't find the HostZone", - userAccount: *defaultUA, - hostZone: nil, + userAccount: *defaultUA, + hostZone: nil, + stakeibcHostZone: defaultIcaHZ, + + expectedErrorContains: types.ErrHostZoneNotFound.Error(), + }, + { + testName: "[Error] Can't find the stakeibc HostZone", + + userAccount: *defaultUA, + hostZone: defaultMsHZ, + stakeibcHostZone: nil, expectedErrorContains: types.ErrHostZoneNotFound.Error(), }, @@ -142,10 +192,11 @@ func (s *KeeperTestSuite) TestRedeemStake() { userAccount: *defaultUA, hostZone: func() *types.HostZone { - _, hz, _, _, _ := s.getDefaultTestInputs() + _, hz, _, _, _, _ := s.getDefaultTestInputs() hz.RedemptionAddress = "nonparsable-address" return hz }(), + stakeibcHostZone: defaultIcaHZ, expectedErrorContains: "could not bech32 decode redemption address", }, @@ -154,10 +205,11 @@ func (s *KeeperTestSuite) TestRedeemStake() { userAccount: *defaultUA, hostZone: func() *types.HostZone { - _, hz, _, _, _ := s.getDefaultTestInputs() + _, hz, _, _, _, _ := s.getDefaultTestInputs() hz.Halted = true return hz }(), + stakeibcHostZone: defaultIcaHZ, expectedErrorContains: types.ErrHostZoneHalted.Error(), }, @@ -165,8 +217,9 @@ func (s *KeeperTestSuite) TestRedeemStake() { testName: "[Error] RedemptionRate outside of bounds", userAccount: *defaultUA, - hostZone: func() *types.HostZone { - _, hz, _, _, _ := s.getDefaultTestInputs() + hostZone: defaultMsHZ, + stakeibcHostZone: func() *stakeibctypes.HostZone { + _, _, hz, _, _, _ := s.getDefaultTestInputs() hz.RedemptionRate = sdk.MustNewDecFromStr("5.2") return hz }(), @@ -176,9 +229,10 @@ func (s *KeeperTestSuite) TestRedeemStake() { { testName: "[Error] No Accumulating UndondingRecord", - userAccount: *defaultUA, - hostZone: defaultHZ, - accUnbondRecord: nil, + userAccount: *defaultUA, + hostZone: defaultMsHZ, + stakeibcHostZone: defaultIcaHZ, + accUnbondRecord: nil, expectedErrorContains: types.ErrBrokenUnbondingRecordInvariant.Error(), }, @@ -186,13 +240,14 @@ func (s *KeeperTestSuite) TestRedeemStake() { testName: "[Error] Not enough tokens in wallet", userAccount: func() Account { - acc, _, _, _, _ := s.getDefaultTestInputs() + acc, _, _, _, _, _ := s.getDefaultTestInputs() acc.stTokens.Amount = sdk.NewInt(500_000) return *acc }(), - hostZone: defaultHZ, - accUnbondRecord: defaultUR, - redeemMsg: *defaultMsg, // attempt to redeem 1_000_000 stTokens + hostZone: defaultMsHZ, + stakeibcHostZone: defaultIcaHZ, + accUnbondRecord: defaultUR, + redeemMsg: *defaultMsg, // attempt to redeem 1_000_000 stTokens expectedErrorContains: sdkerrors.ErrInsufficientFunds.Error(), }, @@ -200,31 +255,72 @@ func (s *KeeperTestSuite) TestRedeemStake() { testName: "[Error] Redeeming more than HostZone delegation total", userAccount: func() Account { - acc, _, _, _, _ := s.getDefaultTestInputs() + acc, _, _, _, _, _ := s.getDefaultTestInputs() acc.stTokens.Amount = sdk.NewInt(5_000_000_000) return *acc }(), - hostZone: defaultHZ, // 1_000_000_000 total delegation - accUnbondRecord: defaultUR, + hostZone: defaultMsHZ, // 1_000_000_000 total delegation + stakeibcHostZone: defaultIcaHZ, + accUnbondRecord: defaultUR, redeemMsg: func() types.MsgRedeemStake { - _, _, _, _, msg := s.getDefaultTestInputs() + _, _, _, _, _, msg := s.getDefaultTestInputs() msg.StTokenAmount = sdk.NewInt(5_000_000_000) return *msg }(), expectedErrorContains: types.ErrUnbondAmountToLarge.Error(), }, + { + testName: "[Error] Redeeming is disabled", + + userAccount: *defaultUA, + hostZone: func() *types.HostZone { + _, hz, _, _, _, _ := s.getDefaultTestInputs() + hz.RemainingDelegatedBalance = sdkmath.ZeroInt() + return hz + }(), + stakeibcHostZone: defaultIcaHZ, + accUnbondRecord: defaultUR, + redeemMsg: *defaultMsg, + + expectedErrorContains: types.ErrRedemptionsDisabled.Error(), + }, + { + testName: "[Error] Spillover fails in stakeibc", + + userAccount: *defaultUA, + hostZone: func() *types.HostZone { + _, hz, _, _, _, msg := s.getDefaultTestInputs() + hz.RemainingDelegatedBalance = msg.StTokenAmount.Sub(sdkmath.OneInt()) // subtract 1 so there's excess + return hz + }(), + stakeibcHostZone: func() *stakeibctypes.HostZone { + _, _, hz, _, _, _ := s.getDefaultTestInputs() + hz.RedemptionRate = sdk.OneDec() + return hz + }(), + accUnbondRecord: defaultUR, + redeemMsg: func() types.MsgRedeemStake { + // Make receiver address invalid so stakeibc fails + _, _, _, _, _, msg := s.getDefaultTestInputs() + msg.Receiver = "" + return *msg + }(), + + expectedErrorContains: "unable to execute stakeibc redeem stake", + }, { testName: "[Success] No RR exists yet, RedeemStake tx creates one", userAccount: *defaultUA, - hostZone: defaultHZ, + hostZone: defaultMsHZ, + stakeibcHostZone: defaultIcaHZ, accUnbondRecord: defaultUR, redemptionRecord: nil, redeemMsg: *defaultMsg, // redeem 1_000_000 stTokens expectedUnbondingRecord: func() *types.UnbondingRecord { - _, hz, ur, _, msg := s.getDefaultTestInputs() + _, _, hz, ur, _, msg := s.getDefaultTestInputs() ur.StTokenAmount = ur.StTokenAmount.Add(msg.StTokenAmount) nativeDiff := sdk.NewDecFromInt(msg.StTokenAmount).Mul(hz.RedemptionRate).TruncateInt() ur.NativeAmount = ur.NativeAmount.Add(nativeDiff) @@ -234,33 +330,95 @@ func (s *KeeperTestSuite) TestRedeemStake() { UnbondingRecordId: defaultUR.Id, Redeemer: defaultMsg.Redeemer, StTokenAmount: defaultMsg.StTokenAmount, - NativeAmount: sdk.NewDecFromInt(defaultMsg.StTokenAmount).Mul(defaultHZ.RedemptionRate).TruncateInt(), + NativeAmount: sdk.NewDecFromInt(defaultMsg.StTokenAmount).Mul(defaultIcaHZ.RedemptionRate).TruncateInt(), }, }, { testName: "[Success] RR exists already for redeemer, RedeemStake tx updates", userAccount: *defaultUA, - hostZone: defaultHZ, + hostZone: defaultMsHZ, + stakeibcHostZone: defaultIcaHZ, accUnbondRecord: defaultUR, redemptionRecord: defaultRR, // previous redeemption of 400_000 redeemMsg: *defaultMsg, // redeem 1_000_000 stTokens expectedUnbondingRecord: func() *types.UnbondingRecord { - _, hz, ur, _, msg := s.getDefaultTestInputs() + _, _, hz, ur, _, msg := s.getDefaultTestInputs() ur.StTokenAmount = ur.StTokenAmount.Add(msg.StTokenAmount) nativeDiff := sdk.NewDecFromInt(msg.StTokenAmount).Mul(hz.RedemptionRate).TruncateInt() ur.NativeAmount = ur.NativeAmount.Add(nativeDiff) return ur }(), expectedRedemptionRecord: func() *types.RedemptionRecord { - _, hz, _, rr, msg := s.getDefaultTestInputs() + _, _, hz, _, rr, msg := s.getDefaultTestInputs() rr.StTokenAmount = rr.StTokenAmount.Add(msg.StTokenAmount) nativeDiff := sdk.NewDecFromInt(msg.StTokenAmount).Mul(hz.RedemptionRate).TruncateInt() rr.NativeAmount = rr.NativeAmount.Add(nativeDiff) return rr }(), }, + { + testName: "[Success] Redeems all remaining balance", + + userAccount: *defaultUA, + hostZone: func() *types.HostZone { + _, msHz, icaHz, _, _, msg := s.getDefaultTestInputs() + nativeRedeemAmount := sdk.NewDecFromInt(msg.StTokenAmount).Mul(icaHz.RedemptionRate).TruncateInt() + msHz.RemainingDelegatedBalance = nativeRedeemAmount + return msHz + }(), + stakeibcHostZone: defaultIcaHZ, + accUnbondRecord: defaultUR, + redeemMsg: *defaultMsg, + + expectedUnbondingRecord: func() *types.UnbondingRecord { + _, _, hz, ur, _, msg := s.getDefaultTestInputs() + ur.StTokenAmount = ur.StTokenAmount.Add(msg.StTokenAmount) + nativeDiff := sdk.NewDecFromInt(msg.StTokenAmount).Mul(hz.RedemptionRate).TruncateInt() + ur.NativeAmount = ur.NativeAmount.Add(nativeDiff) + return ur + }(), + expectedRedemptionRecord: &types.RedemptionRecord{ + UnbondingRecordId: defaultUR.Id, + Redeemer: defaultMsg.Redeemer, + StTokenAmount: defaultMsg.StTokenAmount, + NativeAmount: sdk.NewDecFromInt(defaultMsg.StTokenAmount).Mul(defaultIcaHZ.RedemptionRate).TruncateInt(), + }, + expectedStakeibcRedemptionsEnabled: true, + }, + { + testName: "[Success] Redeems with stakeibc spillover", + + userAccount: *defaultUA, + hostZone: func() *types.HostZone { + _, hz, _, _, _, msg := s.getDefaultTestInputs() + hz.RemainingDelegatedBalance = msg.StTokenAmount.Sub(sdkmath.OneInt()) // subtract 1 so there's excess + return hz + }(), + stakeibcHostZone: func() *stakeibctypes.HostZone { + _, _, hz, _, _, _ := s.getDefaultTestInputs() + hz.RedemptionRate = sdk.OneDec() + return hz + }(), + accUnbondRecord: defaultUR, + redeemMsg: *defaultMsg, + + expectedUnbondingRecord: func() *types.UnbondingRecord { + _, _, _, ur, _, msg := s.getDefaultTestInputs() + ur.StTokenAmount = ur.StTokenAmount.Add(msg.StTokenAmount).Sub(sdkmath.OneInt()) + ur.NativeAmount = ur.NativeAmount.Add(msg.StTokenAmount).Sub(sdkmath.OneInt()) + return ur + }(), + expectedRedemptionRecord: &types.RedemptionRecord{ + UnbondingRecordId: defaultUR.Id, + Redeemer: defaultMsg.Redeemer, + StTokenAmount: defaultMsg.StTokenAmount.Sub(sdkmath.OneInt()), + NativeAmount: defaultMsg.StTokenAmount.Sub(sdkmath.OneInt()), + }, + expectedStakeibcRedemptionAmount: sdkmath.OneInt(), + expectedStakeibcRedemptionsEnabled: true, + }, } for _, tc := range testCases { @@ -273,7 +431,7 @@ func (s *KeeperTestSuite) TestRedeemStake() { func (s *KeeperTestSuite) checkRedeemStakeTestCase(tc RedeemStakeTestCase) { s.SetupTest() // reset state - s.SetupTestRedeemStake(tc.userAccount, tc.hostZone, tc.accUnbondRecord, tc.redemptionRecord) + s.SetupTestRedeemStake(tc.userAccount, tc.hostZone, tc.stakeibcHostZone, tc.accUnbondRecord, tc.redemptionRecord) startingStEscrowBalance := sdk.NewInt64Coin(StDenom, 0) if tc.hostZone != nil { @@ -284,11 +442,18 @@ func (s *KeeperTestSuite) checkRedeemStakeTestCase(tc RedeemStakeTestCase) { } // Run the RedeemStake, verify expected errors returned or no errors with expected updates to records - _, err := s.App.StaketiaKeeper.RedeemStake(s.Ctx, tc.redeemMsg.Redeemer, tc.redeemMsg.StTokenAmount) + _, err := s.App.StaketiaKeeper.RedeemStake(s.Ctx, tc.redeemMsg.Redeemer, tc.redeemMsg.Receiver, tc.redeemMsg.StTokenAmount) if tc.expectedErrorContains == "" { // Successful Run Test Case s.Require().NoError(err, "No error expected during redeem stake execution") + // Check the remaining delegated amount was decremented (and should never go below 0) + hostZone := s.MustGetHostZone() + redeemAmount := sdk.NewDecFromInt(tc.redeemMsg.StTokenAmount).Mul(tc.stakeibcHostZone.RedemptionRate).TruncateInt() + expectedRemainingDelegation := tc.hostZone.RemainingDelegatedBalance.Sub(redeemAmount) + expectedRemainingDelegation = sdkmath.MaxInt(expectedRemainingDelegation, sdkmath.ZeroInt()) + s.Require().Equal(expectedRemainingDelegation.Int64(), hostZone.RemainingDelegatedBalance.Int64(), "remaining delegated balance") + // check expected updates to Accumulating UnbondingRecord currentAUR, err := s.App.StaketiaKeeper.GetAccumulatingUnbondingRecord(s.Ctx) s.Require().NoError(err, "No error expected when getting UnbondingRecord") @@ -306,6 +471,19 @@ func (s *KeeperTestSuite) checkRedeemStakeTestCase(tc RedeemStakeTestCase) { currentStEscrowBalance := s.App.BankKeeper.GetBalance(s.Ctx, escrowAccount, StDenom) s.Require().NotEqual(startingStEscrowBalance, currentStEscrowBalance, "Escrowed balance should have changed") s.Require().Equal(currentStEscrowBalance.Amount, currentAUR.StTokenAmount, "Escrowed balance does not match the UnbondingRecord") + + // If all the remaining amount was unbonded, check that redemptions were enabled + stakeibcHostZone, found := s.App.StakeibcKeeper.GetHostZone(s.Ctx, types.CelestiaChainId) + s.Require().True(found) + s.Require().Equal(tc.expectedStakeibcRedemptionsEnabled, stakeibcHostZone.RedemptionsEnabled, "stakeibc redemptions enabled") + + // If there's stakeibc spillover, check that the amount was stored in the user redemption record + if !tc.expectedStakeibcRedemptionAmount.IsNil() { + userRedemptionRecords := s.App.RecordsKeeper.GetAllUserRedemptionRecord(s.Ctx) + s.Require().Len(userRedemptionRecords, 1, "there should be a stakeibc user redemption record") + s.Require().Equal(tc.expectedStakeibcRedemptionAmount.Int64(), userRedemptionRecords[0].StTokenAmount.Int64(), + "stakeibc user redemption record amount") + } } else { // Expected Error Test Case s.Require().Error(err, "Error expected to be returned but none found") @@ -331,7 +509,8 @@ func (s *KeeperTestSuite) TestPrepareUndelegation() { // (an uneven number is used to test rounding/truncation) oldRedemptionRate := sdk.MustNewDecFromStr("1.9") redemptionRate := sdk.MustNewDecFromStr("1.999") - s.App.StaketiaKeeper.SetHostZone(s.Ctx, types.HostZone{ + s.App.StakeibcKeeper.SetHostZone(s.Ctx, stakeibctypes.HostZone{ + ChainId: types.CelestiaChainId, RedemptionRate: redemptionRate, }) @@ -418,12 +597,13 @@ func (s *KeeperTestSuite) TestPrepareUndelegation() { s.Require().ErrorContains(err, "more than one record in status ACCUMULATING") // Halt the host zone and try again - it should fail - hostZone := s.MustGetHostZone() + hostZone, found := s.App.StakeibcKeeper.GetHostZone(s.Ctx, types.CelestiaChainId) + s.Require().True(found) hostZone.Halted = true - s.App.StaketiaKeeper.SetHostZone(s.Ctx, hostZone) + s.App.StakeibcKeeper.SetHostZone(s.Ctx, hostZone) err = s.App.StaketiaKeeper.PrepareUndelegation(s.Ctx, epochNumber) - s.Require().ErrorContains(err, "host zone is halted") + s.Require().ErrorContains(err, "host zone celestia is halted") } // ---------------------------------------------- @@ -438,7 +618,8 @@ type ConfirmUndelegationTestCase struct { amountToUndelegate sdkmath.Int delegatedBalance sdkmath.Int redemptionAccountBalance sdkmath.Int - hostZone types.HostZone + staketiaHostZone types.HostZone + stakeibcHostZone stakeibctypes.HostZone expectedUnbondingTime uint64 } @@ -453,16 +634,19 @@ func (s *KeeperTestSuite) SetupTestConfirmUndelegation(amountToUndelegate sdkmat expectedUnbondingTime := uint64(s.Ctx.BlockTime().Add(time.Minute * 2).Unix()) // Create a host zone with delegatedBalance and RedemptionAddresses - hostZone := types.HostZone{ - DelegatedBalance: delegatedBalance, + staketiaHostZone := types.HostZone{ RedemptionAddress: redemptionAddress.String(), NativeTokenDenom: HostNativeDenom, UnbondingPeriodSeconds: unbondingPeriodSeconds, - MinRedemptionRate: sdk.MustNewDecFromStr("0.9"), - MaxRedemptionRate: sdk.MustNewDecFromStr("1.2"), - RedemptionRate: sdk.MustNewDecFromStr("1.1"), } - s.App.StaketiaKeeper.SetHostZone(s.Ctx, hostZone) + s.App.StaketiaKeeper.SetHostZone(s.Ctx, staketiaHostZone) + + stakeibcHostZone := stakeibctypes.HostZone{ + ChainId: types.CelestiaChainId, + RedemptionRate: sdk.MustNewDecFromStr("1.1"), + TotalDelegations: delegatedBalance, + } + s.App.StakeibcKeeper.SetHostZone(s.Ctx, stakeibcHostZone) // Fund the redemption account with tokens that will be burned stTokensInRedemption := sdk.NewCoin(StDenom, redemptionAccountBalance) @@ -470,7 +654,7 @@ func (s *KeeperTestSuite) SetupTestConfirmUndelegation(amountToUndelegate sdkmat // create an unbonding record in status UNBONDING_QUEUE // - stToken amount to burn as if the RR is 1.1 - stTokenAmountToBurn := sdk.NewDecFromInt(amountToUndelegate).Mul(hostZone.RedemptionRate).TruncateInt() + stTokenAmountToBurn := sdk.NewDecFromInt(amountToUndelegate).Mul(stakeibcHostZone.RedemptionRate).TruncateInt() unbondingRecord := types.UnbondingRecord{ Id: 1, Status: types.UNBONDING_QUEUE, @@ -487,7 +671,8 @@ func (s *KeeperTestSuite) SetupTestConfirmUndelegation(amountToUndelegate sdkmat amountToUndelegate: amountToUndelegate, delegatedBalance: delegatedBalance, redemptionAccountBalance: redemptionAccountBalance, - hostZone: hostZone, + stakeibcHostZone: stakeibcHostZone, + staketiaHostZone: staketiaHostZone, expectedUnbondingTime: expectedUnbondingTime, } return tc @@ -517,8 +702,9 @@ func (s *KeeperTestSuite) TestConfirmUndelegation_Success() { s.Require().Equal(expectedRedemptionAccountBalance, actualRedemptionAccountBalance, "redemption account balance") // check that delegated balance was updated - hostZone := s.MustGetHostZone() - s.Require().Equal(tc.delegatedBalance.Sub(tc.amountToUndelegate), hostZone.DelegatedBalance, "delegated balance") + stakeibcHostZone, found := s.App.StakeibcKeeper.GetHostZone(s.Ctx, types.CelestiaChainId) + s.Require().True(found) + s.Require().Equal(tc.delegatedBalance.Sub(tc.amountToUndelegate), stakeibcHostZone.TotalDelegations, "delegated balance") } // unit test ConfirmUndelegation with nothing to unbond @@ -642,113 +828,6 @@ func (s *KeeperTestSuite) TestBurnRedeemedStTokens_BadRedemptionAddress() { s.Require().Error(err, "could not bech32 decode addres") } -func (s *KeeperTestSuite) TestVerifyImpliedRedemptionRateFromUnbonding() { - minRRBound := sdk.MustNewDecFromStr("0.9") - maxRRBound := sdk.MustNewDecFromStr("1.1") - - testCases := []struct { - name string - delegatedBalanceBefore sdkmath.Int - delegatedBalanceAfter sdkmath.Int - stTokenSupplyBefore sdkmath.Int - stTokenSupplyAfter sdkmath.Int - expectedError string - }{ - { - // Undelegated: 1000, Burned: 1000, Implied Rate: 1.0 - name: "valid implied rate - 1", - delegatedBalanceBefore: sdkmath.NewInt(5000), - delegatedBalanceAfter: sdkmath.NewInt(4000), // 5000 - 4000 = 1000 undelegated - stTokenSupplyBefore: sdkmath.NewInt(5000), - stTokenSupplyAfter: sdkmath.NewInt(4000), // 5000 - 4000 = 1000 burned - }, - { - // Undelegated: 950, Burned: 1000, Implied Rate: 0.95 - name: "valid implied rate below 1", - delegatedBalanceBefore: sdkmath.NewInt(5000), - delegatedBalanceAfter: sdkmath.NewInt(4050), // 5000 - 4050 = 950 undelegated - stTokenSupplyBefore: sdkmath.NewInt(5000), - stTokenSupplyAfter: sdkmath.NewInt(4000), // 5000 - 4000 = 1000 burned - }, - { - // Undelegated: 1050, Burned: 1000, Implied Rate: 1.05 - name: "valid implied rate above 1", - delegatedBalanceBefore: sdkmath.NewInt(5000), - delegatedBalanceAfter: sdkmath.NewInt(3950), // 5000 - 3950 = 1050 undelegated - stTokenSupplyBefore: sdkmath.NewInt(5000), - stTokenSupplyAfter: sdkmath.NewInt(4000), // 5000 - 4000 = 1000 burned - }, - { - // Undelegated: 900, Burned: 1000, Implied Rate: 0.9 - name: "valid implied rate at min", - delegatedBalanceBefore: sdkmath.NewInt(5000), - delegatedBalanceAfter: sdkmath.NewInt(4000), // 5000 - 4000 = 900 undelegated - stTokenSupplyBefore: sdkmath.NewInt(5000), - stTokenSupplyAfter: sdkmath.NewInt(4000), // 5000 - 4000 = 1000 burned - }, - { - // Undelegated: 1100, Burned: 1000, Implied Rate: 1.1 - name: "valid implied rate at max", - delegatedBalanceBefore: sdkmath.NewInt(5000), - delegatedBalanceAfter: sdkmath.NewInt(3900), // 5000 - 3900 = 1100 undelegated - stTokenSupplyBefore: sdkmath.NewInt(5000), - stTokenSupplyAfter: sdkmath.NewInt(4000), // 5000 - 4000 = 1000 burned - }, - { - // Undelegated: 899, Burned: 1000, Implied Rate: 0.899 - name: "valid implied rate below min", - delegatedBalanceBefore: sdkmath.NewInt(5000), - delegatedBalanceAfter: sdkmath.NewInt(4101), // 5000 - 4101 = 899 undelegated - stTokenSupplyBefore: sdkmath.NewInt(5000), - stTokenSupplyAfter: sdkmath.NewInt(4000), // 5000 - 4000 = 1000 burned - expectedError: "redemption rate outside safety bounds", - }, - { - // Undelegated: 1101, Burned: 1000, Implied Rate: 1.101 - name: "valid implied rate above max", - delegatedBalanceBefore: sdkmath.NewInt(5000), - delegatedBalanceAfter: sdkmath.NewInt(3899), // 5000 - 3899 = 1101 undelegated - stTokenSupplyBefore: sdkmath.NewInt(5000), - stTokenSupplyAfter: sdkmath.NewInt(4000), // 5000 - 4000 = 1000 burned - expectedError: "redemption rate outside safety bounds", - }, - { - name: "division by zero", - delegatedBalanceBefore: sdkmath.NewInt(1000), - delegatedBalanceAfter: sdkmath.NewInt(2000), - stTokenSupplyBefore: sdkmath.NewInt(4000), - stTokenSupplyAfter: sdkmath.NewInt(4000), // same as before -> supply change is 0 - expectedError: "division by zero", - }, - } - - for _, tc := range testCases { - s.Run(tc.name, func() { - s.SetupTest() // reset state - - // Mint stTokens to a random account to create supply - s.FundAccount(s.TestAccs[0], sdk.NewCoin(StDenom, tc.stTokenSupplyAfter)) - - // Set the delegated balance on the host zone - s.App.StaketiaKeeper.SetHostZone(s.Ctx, types.HostZone{ - NativeTokenDenom: HostNativeDenom, - DelegatedBalance: tc.delegatedBalanceAfter, - MinRedemptionRate: minRRBound, - MaxRedemptionRate: maxRRBound, - }) - - // verify that the implied redemption rate is between the bounds - err := s.App.StaketiaKeeper.VerifyImpliedRedemptionRateFromUnbonding(s.Ctx, tc.stTokenSupplyBefore, tc.delegatedBalanceBefore) - - if tc.expectedError == "" { - s.Require().NoError(err) - } else { - s.Require().ErrorContains(err, tc.expectedError) - } - }) - } -} - // ---------------------------------------------- // ConfirmUnbondedTokensSwept // ---------------------------------------------- @@ -1031,6 +1110,11 @@ func (s *KeeperTestSuite) SetupTestDistributeClaims() DistributeClaimsTestCase { } s.App.StaketiaKeeper.SetHostZone(s.Ctx, hostZone) + // Create unhalted stakeibc host zone + s.App.StakeibcKeeper.SetHostZone(s.Ctx, stakeibctypes.HostZone{ + ChainId: types.CelestiaChainId, + }) + // Define unbonding records with different statuses claimableRecordIds := []uint64{1, 3} unbondingRecords := []types.UnbondingRecord{ diff --git a/x/staketia/legacytypes/staketia.pb.go b/x/staketia/legacytypes/staketia.pb.go new file mode 100644 index 0000000000..b647ac9acc --- /dev/null +++ b/x/staketia/legacytypes/staketia.pb.go @@ -0,0 +1,2739 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: stride/staketia/staketia.proto + +package types + +import ( + fmt "fmt" + _ "github.com/cosmos/cosmos-proto" + github_com_cosmos_cosmos_sdk_types "github.com/cosmos/cosmos-sdk/types" + _ "github.com/cosmos/gogoproto/gogoproto" + proto "github.com/cosmos/gogoproto/proto" + io "io" + math "math" + math_bits "math/bits" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +// Status fields for a delegation record +// Note: There is an important assumption here that tokens in the deposit +// account should not be tracked by these records. The record is created as soon +// as the tokens leave stride +// Additionally, the GetActiveDelegationRecords query filters for records that +// are either TRANSFER_IN_PROGERSS or DELEGATION_QUEUE. If a new active status +// is added, the keeper must be modified +type DelegationRecordStatus int32 + +const ( + // TRANSFER_IN_PROGRESS indicates the native tokens are being sent from the + // deposit account to the delegation account + TRANSFER_IN_PROGRESS DelegationRecordStatus = 0 + // TRANSFER_FAILED indicates that the transfer either timed out or was an ack + // failure + TRANSFER_FAILED DelegationRecordStatus = 1 + // DELEGATION_QUEUE indicates the tokens have landed on the host zone and are + // ready to be delegated + DELEGATION_QUEUE DelegationRecordStatus = 2 + // DELEGATION_COMPLETE indicates the delegation has been completed + DELEGATION_COMPLETE DelegationRecordStatus = 3 +) + +var DelegationRecordStatus_name = map[int32]string{ + 0: "TRANSFER_IN_PROGRESS", + 1: "TRANSFER_FAILED", + 2: "DELEGATION_QUEUE", + 3: "DELEGATION_COMPLETE", +} + +var DelegationRecordStatus_value = map[string]int32{ + "TRANSFER_IN_PROGRESS": 0, + "TRANSFER_FAILED": 1, + "DELEGATION_QUEUE": 2, + "DELEGATION_COMPLETE": 3, +} + +func (x DelegationRecordStatus) String() string { + return proto.EnumName(DelegationRecordStatus_name, int32(x)) +} + +func (DelegationRecordStatus) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_d306d9365b78f7b2, []int{0} +} + +// Status fields for an unbonding record +type UnbondingRecordStatus int32 + +const ( + // ACCUMULATING_REDEMPTIONS indicates redemptions are still being accumulated + // on this record + ACCUMULATING_REDEMPTIONS UnbondingRecordStatus = 0 + // UNBONDING_QUEUE indicates the unbond amount for this epoch has been froze + // and the tokens are ready to be unbonded on the host zone + UNBONDING_QUEUE UnbondingRecordStatus = 1 + // UNBONDING_IN_PROGRESS indicates the unbonding is currently in progress on + // the host zone + UNBONDING_IN_PROGRESS UnbondingRecordStatus = 2 + // UNBONDED indicates the unbonding is finished on the host zone and the + // tokens are still in the delegation account + UNBONDED UnbondingRecordStatus = 3 + // CLAIMABLE indicates the unbonded tokens have been swept to stride and are + // ready to be distributed to users + CLAIMABLE UnbondingRecordStatus = 4 + // CLAIMED indicates the full unbonding cycle has been completed + CLAIMED UnbondingRecordStatus = 5 +) + +var UnbondingRecordStatus_name = map[int32]string{ + 0: "ACCUMULATING_REDEMPTIONS", + 1: "UNBONDING_QUEUE", + 2: "UNBONDING_IN_PROGRESS", + 3: "UNBONDED", + 4: "CLAIMABLE", + 5: "CLAIMED", +} + +var UnbondingRecordStatus_value = map[string]int32{ + "ACCUMULATING_REDEMPTIONS": 0, + "UNBONDING_QUEUE": 1, + "UNBONDING_IN_PROGRESS": 2, + "UNBONDED": 3, + "CLAIMABLE": 4, + "CLAIMED": 5, +} + +func (x UnbondingRecordStatus) String() string { + return proto.EnumName(UnbondingRecordStatus_name, int32(x)) +} + +func (UnbondingRecordStatus) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_d306d9365b78f7b2, []int{1} +} + +type HostZone struct { + // Chain ID + ChainId string `protobuf:"bytes,1,opt,name=chain_id,json=chainId,proto3" json:"chain_id,omitempty"` + // Native token denom on the host zone (e.g. utia) + NativeTokenDenom string `protobuf:"bytes,2,opt,name=native_token_denom,json=nativeTokenDenom,proto3" json:"native_token_denom,omitempty"` + // IBC denom of the native token as it lives on stride (e.g. ibc/...) + NativeTokenIbcDenom string `protobuf:"bytes,3,opt,name=native_token_ibc_denom,json=nativeTokenIbcDenom,proto3" json:"native_token_ibc_denom,omitempty"` + // Transfer channel ID from stride to the host zone + TransferChannelId string `protobuf:"bytes,4,opt,name=transfer_channel_id,json=transferChannelId,proto3" json:"transfer_channel_id,omitempty"` + // Operator controlled delegation address on the host zone + DelegationAddress string `protobuf:"bytes,5,opt,name=delegation_address,json=delegationAddress,proto3" json:"delegation_address,omitempty"` + // Operator controlled reward address on the host zone + RewardAddress string `protobuf:"bytes,6,opt,name=reward_address,json=rewardAddress,proto3" json:"reward_address,omitempty"` + // Deposit address on stride + DepositAddress string `protobuf:"bytes,7,opt,name=deposit_address,json=depositAddress,proto3" json:"deposit_address,omitempty"` + // Redemption address on stride + RedemptionAddress string `protobuf:"bytes,8,opt,name=redemption_address,json=redemptionAddress,proto3" json:"redemption_address,omitempty"` + // Claim address on stride + ClaimAddress string `protobuf:"bytes,9,opt,name=claim_address,json=claimAddress,proto3" json:"claim_address,omitempty"` + // operator address set by safe, on stride + OperatorAddressOnStride string `protobuf:"bytes,10,opt,name=operator_address_on_stride,json=operatorAddressOnStride,proto3" json:"operator_address_on_stride,omitempty"` + // admin address set upon host zone creation, on stride + SafeAddressOnStride string `protobuf:"bytes,11,opt,name=safe_address_on_stride,json=safeAddressOnStride,proto3" json:"safe_address_on_stride,omitempty"` + // Previous redemption rate + LastRedemptionRate github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,12,opt,name=last_redemption_rate,json=lastRedemptionRate,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"last_redemption_rate"` + // Current redemption rate + RedemptionRate github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,13,opt,name=redemption_rate,json=redemptionRate,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"redemption_rate"` + // Min outer redemption rate - adjusted by governance + MinRedemptionRate github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,14,opt,name=min_redemption_rate,json=minRedemptionRate,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"min_redemption_rate"` + // Max outer redemption rate - adjusted by governance + MaxRedemptionRate github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,15,opt,name=max_redemption_rate,json=maxRedemptionRate,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"max_redemption_rate"` + // Min inner redemption rate - adjusted by controller + MinInnerRedemptionRate github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,16,opt,name=min_inner_redemption_rate,json=minInnerRedemptionRate,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"min_inner_redemption_rate"` + // Max inner redemption rate - adjusted by controller + MaxInnerRedemptionRate github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,17,opt,name=max_inner_redemption_rate,json=maxInnerRedemptionRate,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"max_inner_redemption_rate"` + // Total delegated balance on the host zone delegation account + DelegatedBalance github_com_cosmos_cosmos_sdk_types.Int `protobuf:"bytes,18,opt,name=delegated_balance,json=delegatedBalance,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Int" json:"delegated_balance"` + // The undelegation period for Celestia in days + UnbondingPeriodSeconds uint64 `protobuf:"varint,19,opt,name=unbonding_period_seconds,json=unbondingPeriodSeconds,proto3" json:"unbonding_period_seconds,omitempty"` + // Indicates whether the host zone has been halted + Halted bool `protobuf:"varint,20,opt,name=halted,proto3" json:"halted,omitempty"` +} + +func (m *HostZone) Reset() { *m = HostZone{} } +func (m *HostZone) String() string { return proto.CompactTextString(m) } +func (*HostZone) ProtoMessage() {} +func (*HostZone) Descriptor() ([]byte, []int) { + return fileDescriptor_d306d9365b78f7b2, []int{0} +} +func (m *HostZone) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *HostZone) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_HostZone.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *HostZone) XXX_Merge(src proto.Message) { + xxx_messageInfo_HostZone.Merge(m, src) +} +func (m *HostZone) XXX_Size() int { + return m.Size() +} +func (m *HostZone) XXX_DiscardUnknown() { + xxx_messageInfo_HostZone.DiscardUnknown(m) +} + +var xxx_messageInfo_HostZone proto.InternalMessageInfo + +func (m *HostZone) GetChainId() string { + if m != nil { + return m.ChainId + } + return "" +} + +func (m *HostZone) GetNativeTokenDenom() string { + if m != nil { + return m.NativeTokenDenom + } + return "" +} + +func (m *HostZone) GetNativeTokenIbcDenom() string { + if m != nil { + return m.NativeTokenIbcDenom + } + return "" +} + +func (m *HostZone) GetTransferChannelId() string { + if m != nil { + return m.TransferChannelId + } + return "" +} + +func (m *HostZone) GetDelegationAddress() string { + if m != nil { + return m.DelegationAddress + } + return "" +} + +func (m *HostZone) GetRewardAddress() string { + if m != nil { + return m.RewardAddress + } + return "" +} + +func (m *HostZone) GetDepositAddress() string { + if m != nil { + return m.DepositAddress + } + return "" +} + +func (m *HostZone) GetRedemptionAddress() string { + if m != nil { + return m.RedemptionAddress + } + return "" +} + +func (m *HostZone) GetClaimAddress() string { + if m != nil { + return m.ClaimAddress + } + return "" +} + +func (m *HostZone) GetOperatorAddressOnStride() string { + if m != nil { + return m.OperatorAddressOnStride + } + return "" +} + +func (m *HostZone) GetSafeAddressOnStride() string { + if m != nil { + return m.SafeAddressOnStride + } + return "" +} + +func (m *HostZone) GetUnbondingPeriodSeconds() uint64 { + if m != nil { + return m.UnbondingPeriodSeconds + } + return 0 +} + +func (m *HostZone) GetHalted() bool { + if m != nil { + return m.Halted + } + return false +} + +// DelegationRecords track the aggregate liquid stakes and delegations +// for a given epoch +// Note: There is an important assumption here that tokens in the deposit +// account should not be tracked by these records. The record is created as soon +// as the tokens leave stride +type DelegationRecord struct { + // Deposit record unique ID + Id uint64 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"` + // The amount of native tokens that should be delegated + NativeAmount github_com_cosmos_cosmos_sdk_types.Int `protobuf:"bytes,2,opt,name=native_amount,json=nativeAmount,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Int" json:"native_amount"` + // The status indicating the point in the delegation's lifecycle + Status DelegationRecordStatus `protobuf:"varint,3,opt,name=status,proto3,enum=stride.staketia.DelegationRecordStatus" json:"status,omitempty"` + // The tx hash of the delegation on the host zone + TxHash string `protobuf:"bytes,4,opt,name=tx_hash,json=txHash,proto3" json:"tx_hash,omitempty"` +} + +func (m *DelegationRecord) Reset() { *m = DelegationRecord{} } +func (m *DelegationRecord) String() string { return proto.CompactTextString(m) } +func (*DelegationRecord) ProtoMessage() {} +func (*DelegationRecord) Descriptor() ([]byte, []int) { + return fileDescriptor_d306d9365b78f7b2, []int{1} +} +func (m *DelegationRecord) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *DelegationRecord) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_DelegationRecord.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *DelegationRecord) XXX_Merge(src proto.Message) { + xxx_messageInfo_DelegationRecord.Merge(m, src) +} +func (m *DelegationRecord) XXX_Size() int { + return m.Size() +} +func (m *DelegationRecord) XXX_DiscardUnknown() { + xxx_messageInfo_DelegationRecord.DiscardUnknown(m) +} + +var xxx_messageInfo_DelegationRecord proto.InternalMessageInfo + +func (m *DelegationRecord) GetId() uint64 { + if m != nil { + return m.Id + } + return 0 +} + +func (m *DelegationRecord) GetStatus() DelegationRecordStatus { + if m != nil { + return m.Status + } + return TRANSFER_IN_PROGRESS +} + +func (m *DelegationRecord) GetTxHash() string { + if m != nil { + return m.TxHash + } + return "" +} + +// UnbondingRecords track the aggregate unbondings across an epoch +type UnbondingRecord struct { + // Unbonding record ID + Id uint64 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"` + // The status indicating the point in the delegation's lifecycle + Status UnbondingRecordStatus `protobuf:"varint,2,opt,name=status,proto3,enum=stride.staketia.UnbondingRecordStatus" json:"status,omitempty"` + // The amount of stTokens that were redeemed + StTokenAmount github_com_cosmos_cosmos_sdk_types.Int `protobuf:"bytes,3,opt,name=st_token_amount,json=stTokenAmount,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Int" json:"st_token_amount"` + // The corresponding amount of native tokens that should be unbonded + NativeAmount github_com_cosmos_cosmos_sdk_types.Int `protobuf:"bytes,4,opt,name=native_amount,json=nativeAmount,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Int" json:"native_amount"` + // The Unix timestamp (in seconds) at which the unbonding completes + UnbondingCompletionTimeSeconds uint64 `protobuf:"varint,5,opt,name=unbonding_completion_time_seconds,json=unbondingCompletionTimeSeconds,proto3" json:"unbonding_completion_time_seconds,omitempty"` + // The tx hash of the undelegation on the host zone + UndelegationTxHash string `protobuf:"bytes,6,opt,name=undelegation_tx_hash,json=undelegationTxHash,proto3" json:"undelegation_tx_hash,omitempty"` + // The tx hash of the unbonded token sweep on the host zone + UnbondedTokenSweepTxHash string `protobuf:"bytes,7,opt,name=unbonded_token_sweep_tx_hash,json=unbondedTokenSweepTxHash,proto3" json:"unbonded_token_sweep_tx_hash,omitempty"` +} + +func (m *UnbondingRecord) Reset() { *m = UnbondingRecord{} } +func (m *UnbondingRecord) String() string { return proto.CompactTextString(m) } +func (*UnbondingRecord) ProtoMessage() {} +func (*UnbondingRecord) Descriptor() ([]byte, []int) { + return fileDescriptor_d306d9365b78f7b2, []int{2} +} +func (m *UnbondingRecord) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *UnbondingRecord) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_UnbondingRecord.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *UnbondingRecord) XXX_Merge(src proto.Message) { + xxx_messageInfo_UnbondingRecord.Merge(m, src) +} +func (m *UnbondingRecord) XXX_Size() int { + return m.Size() +} +func (m *UnbondingRecord) XXX_DiscardUnknown() { + xxx_messageInfo_UnbondingRecord.DiscardUnknown(m) +} + +var xxx_messageInfo_UnbondingRecord proto.InternalMessageInfo + +func (m *UnbondingRecord) GetId() uint64 { + if m != nil { + return m.Id + } + return 0 +} + +func (m *UnbondingRecord) GetStatus() UnbondingRecordStatus { + if m != nil { + return m.Status + } + return ACCUMULATING_REDEMPTIONS +} + +func (m *UnbondingRecord) GetUnbondingCompletionTimeSeconds() uint64 { + if m != nil { + return m.UnbondingCompletionTimeSeconds + } + return 0 +} + +func (m *UnbondingRecord) GetUndelegationTxHash() string { + if m != nil { + return m.UndelegationTxHash + } + return "" +} + +func (m *UnbondingRecord) GetUnbondedTokenSweepTxHash() string { + if m != nil { + return m.UnbondedTokenSweepTxHash + } + return "" +} + +// RedemptionRecords track an individual user's redemption claims +type RedemptionRecord struct { + // Unbonding record ID + UnbondingRecordId uint64 `protobuf:"varint,1,opt,name=unbonding_record_id,json=unbondingRecordId,proto3" json:"unbonding_record_id,omitempty"` + // Redeemer + Redeemer string `protobuf:"bytes,2,opt,name=redeemer,proto3" json:"redeemer,omitempty"` + // The amount of stTokens that were redeemed + StTokenAmount github_com_cosmos_cosmos_sdk_types.Int `protobuf:"bytes,3,opt,name=st_token_amount,json=stTokenAmount,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Int" json:"st_token_amount"` + // The corresponding amount of native tokens that should be unbonded + NativeAmount github_com_cosmos_cosmos_sdk_types.Int `protobuf:"bytes,4,opt,name=native_amount,json=nativeAmount,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Int" json:"native_amount"` +} + +func (m *RedemptionRecord) Reset() { *m = RedemptionRecord{} } +func (m *RedemptionRecord) String() string { return proto.CompactTextString(m) } +func (*RedemptionRecord) ProtoMessage() {} +func (*RedemptionRecord) Descriptor() ([]byte, []int) { + return fileDescriptor_d306d9365b78f7b2, []int{3} +} +func (m *RedemptionRecord) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *RedemptionRecord) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_RedemptionRecord.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *RedemptionRecord) XXX_Merge(src proto.Message) { + xxx_messageInfo_RedemptionRecord.Merge(m, src) +} +func (m *RedemptionRecord) XXX_Size() int { + return m.Size() +} +func (m *RedemptionRecord) XXX_DiscardUnknown() { + xxx_messageInfo_RedemptionRecord.DiscardUnknown(m) +} + +var xxx_messageInfo_RedemptionRecord proto.InternalMessageInfo + +func (m *RedemptionRecord) GetUnbondingRecordId() uint64 { + if m != nil { + return m.UnbondingRecordId + } + return 0 +} + +func (m *RedemptionRecord) GetRedeemer() string { + if m != nil { + return m.Redeemer + } + return "" +} + +// SlashRecords log adjustments to the delegated balance +type SlashRecord struct { + // The slash record monotonically increasing ID + Id uint64 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"` + // The Unix timestamp (in seconds) when the slash adjustment was processed on + // stride + Time uint64 `protobuf:"varint,2,opt,name=time,proto3" json:"time,omitempty"` + // The delta by which the total delegated amount changed from slash + NativeAmount github_com_cosmos_cosmos_sdk_types.Int `protobuf:"bytes,3,opt,name=native_amount,json=nativeAmount,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Int" json:"native_amount"` + // The address (or addresses) of the validator that was slashed + ValidatorAddress string `protobuf:"bytes,4,opt,name=validator_address,json=validatorAddress,proto3" json:"validator_address,omitempty"` +} + +func (m *SlashRecord) Reset() { *m = SlashRecord{} } +func (m *SlashRecord) String() string { return proto.CompactTextString(m) } +func (*SlashRecord) ProtoMessage() {} +func (*SlashRecord) Descriptor() ([]byte, []int) { + return fileDescriptor_d306d9365b78f7b2, []int{4} +} +func (m *SlashRecord) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *SlashRecord) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_SlashRecord.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *SlashRecord) XXX_Merge(src proto.Message) { + xxx_messageInfo_SlashRecord.Merge(m, src) +} +func (m *SlashRecord) XXX_Size() int { + return m.Size() +} +func (m *SlashRecord) XXX_DiscardUnknown() { + xxx_messageInfo_SlashRecord.DiscardUnknown(m) +} + +var xxx_messageInfo_SlashRecord proto.InternalMessageInfo + +func (m *SlashRecord) GetId() uint64 { + if m != nil { + return m.Id + } + return 0 +} + +func (m *SlashRecord) GetTime() uint64 { + if m != nil { + return m.Time + } + return 0 +} + +func (m *SlashRecord) GetValidatorAddress() string { + if m != nil { + return m.ValidatorAddress + } + return "" +} + +func init() { + proto.RegisterEnum("stride.staketia.legacy.DelegationRecordStatus", DelegationRecordStatus_name, DelegationRecordStatus_value) + proto.RegisterEnum("stride.staketia.legacy.UnbondingRecordStatus", UnbondingRecordStatus_name, UnbondingRecordStatus_value) + proto.RegisterType((*HostZone)(nil), "stride.staketia.legacy.HostZone") + proto.RegisterType((*DelegationRecord)(nil), "stride.staketia.legacy.DelegationRecord") + proto.RegisterType((*UnbondingRecord)(nil), "stride.staketia.legacy.UnbondingRecord") + proto.RegisterType((*RedemptionRecord)(nil), "stride.staketia.legacy.RedemptionRecord") + proto.RegisterType((*SlashRecord)(nil), "stride.staketia.legacy.SlashRecord") +} + +func init() { proto.RegisterFile("stride/staketia/staketia.proto", fileDescriptor_d306d9365b78f7b2) } + +var fileDescriptor_d306d9365b78f7b2 = []byte{ + // 1119 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xd4, 0x57, 0x4f, 0x6f, 0x1a, 0x47, + 0x14, 0x67, 0x81, 0xd8, 0xe4, 0xc5, 0xc0, 0x32, 0x10, 0xb2, 0xb6, 0x22, 0xe2, 0xfa, 0x90, 0x5a, + 0x69, 0x8d, 0x2b, 0xe7, 0xd2, 0x43, 0x9b, 0x08, 0xc3, 0xc6, 0x59, 0x09, 0x63, 0x77, 0x81, 0x1e, + 0xd2, 0xc3, 0x6a, 0xd8, 0x9d, 0xc0, 0xca, 0xec, 0x2c, 0xda, 0x19, 0x6c, 0x2a, 0xf5, 0xde, 0x4a, + 0xbd, 0xf4, 0xd2, 0x4f, 0xd0, 0x8f, 0xd0, 0x7c, 0x88, 0x48, 0xbd, 0xa4, 0x39, 0x55, 0x3d, 0x44, + 0x95, 0xfd, 0x45, 0xaa, 0x9d, 0xfd, 0x03, 0x06, 0x5b, 0x28, 0x15, 0x97, 0x9e, 0xd8, 0x79, 0xbf, + 0xf7, 0x7e, 0xbf, 0x79, 0xef, 0xcd, 0xec, 0x5b, 0xa0, 0xc2, 0xb8, 0x67, 0x5b, 0x64, 0x9f, 0x71, + 0x7c, 0x46, 0xb8, 0x8d, 0xe3, 0x87, 0xea, 0xc8, 0x73, 0xb9, 0x8b, 0xf2, 0x01, 0x5e, 0x8d, 0xcc, + 0x5b, 0x9b, 0xa6, 0xcb, 0x1c, 0x97, 0x19, 0x02, 0xde, 0x0f, 0x16, 0x81, 0xef, 0x56, 0xa9, 0xef, + 0xf6, 0xdd, 0xc0, 0xee, 0x3f, 0x05, 0xd6, 0x9d, 0x1f, 0x37, 0x20, 0xf3, 0xd2, 0x65, 0xfc, 0x95, + 0x4b, 0x09, 0xda, 0x84, 0x8c, 0x39, 0xc0, 0x36, 0x35, 0x6c, 0x4b, 0x91, 0xb6, 0xa5, 0xdd, 0xbb, + 0xfa, 0xba, 0x58, 0x6b, 0x16, 0xfa, 0x1c, 0x10, 0xc5, 0xdc, 0x3e, 0x27, 0x06, 0x77, 0xcf, 0x08, + 0x35, 0x2c, 0x42, 0x5d, 0x47, 0x49, 0x0a, 0x27, 0x39, 0x40, 0x3a, 0x3e, 0xd0, 0xf0, 0xed, 0xe8, + 0x29, 0x94, 0xaf, 0x79, 0xdb, 0x3d, 0x33, 0x8c, 0x48, 0x89, 0x88, 0xe2, 0x4c, 0x84, 0xd6, 0x33, + 0x83, 0xa0, 0x2a, 0x14, 0xb9, 0x87, 0x29, 0x7b, 0x4d, 0x3c, 0xc3, 0x1c, 0x60, 0x4a, 0xc9, 0xd0, + 0xdf, 0x48, 0x5a, 0x44, 0x14, 0x22, 0xa8, 0x1e, 0x20, 0x9a, 0x85, 0x8e, 0x00, 0x59, 0x64, 0x48, + 0xfa, 0x98, 0xdb, 0x2e, 0x35, 0xb0, 0x65, 0x79, 0x84, 0x31, 0xe5, 0x8e, 0xef, 0x7e, 0xa8, 0xbc, + 0x7f, 0xb3, 0x57, 0x0a, 0xd3, 0xaf, 0x05, 0x48, 0x9b, 0x7b, 0x36, 0xed, 0xeb, 0x85, 0x69, 0x4c, + 0x08, 0xa0, 0xe7, 0x90, 0xf3, 0xc8, 0x05, 0xf6, 0xac, 0x98, 0x64, 0x6d, 0x09, 0x49, 0x36, 0xf0, + 0x8f, 0x08, 0x6a, 0x90, 0xb7, 0xc8, 0xc8, 0x65, 0x36, 0x8f, 0x19, 0xd6, 0x97, 0x30, 0xe4, 0xc2, + 0x80, 0x88, 0xe2, 0x08, 0x90, 0x47, 0x2c, 0xe2, 0x8c, 0xae, 0x25, 0x93, 0x59, 0x96, 0xcc, 0x34, + 0x26, 0x22, 0xfa, 0x1a, 0xb2, 0xe6, 0x10, 0xdb, 0x4e, 0xcc, 0x71, 0x77, 0x09, 0xc7, 0x86, 0x70, + 0x8f, 0xc2, 0xbb, 0xb0, 0xe5, 0x8e, 0x88, 0x87, 0xb9, 0xeb, 0x45, 0x0c, 0x86, 0x4b, 0x8d, 0xe0, + 0x9c, 0x29, 0xb0, 0x84, 0xeb, 0x41, 0x14, 0x1b, 0x9a, 0x4f, 0x68, 0x5b, 0x04, 0xa2, 0x63, 0x28, + 0x33, 0xfc, 0x9a, 0xdc, 0x40, 0x79, 0x6f, 0x09, 0x65, 0xd1, 0x8f, 0x9b, 0xa7, 0xa3, 0x50, 0x1a, + 0x62, 0xc6, 0x8d, 0x99, 0x92, 0x79, 0x98, 0x13, 0x65, 0x43, 0x90, 0x7d, 0xf5, 0xf6, 0xc3, 0xa3, + 0xc4, 0xdf, 0x1f, 0x1e, 0x3d, 0xee, 0xdb, 0x7c, 0x30, 0xee, 0x55, 0x4d, 0xd7, 0x09, 0xaf, 0x42, + 0xf8, 0xb3, 0xc7, 0xac, 0xb3, 0x7d, 0xfe, 0xfd, 0x88, 0xb0, 0x6a, 0x83, 0x98, 0xef, 0xdf, 0xec, + 0x41, 0x28, 0xdd, 0x20, 0xa6, 0x8e, 0x7c, 0x66, 0x3d, 0x26, 0xd6, 0x31, 0x27, 0x88, 0x40, 0x7e, + 0x5e, 0x2a, 0xbb, 0x02, 0xa9, 0x9c, 0x77, 0x5d, 0x66, 0x08, 0x45, 0xc7, 0xa6, 0x0b, 0x59, 0xe5, + 0x56, 0x20, 0x55, 0x70, 0x6c, 0xaa, 0x2f, 0xaa, 0xe1, 0xc9, 0x82, 0x5a, 0x7e, 0x25, 0x6a, 0x78, + 0x32, 0xa7, 0x76, 0x01, 0x9b, 0x7e, 0x6e, 0x36, 0xa5, 0xc4, 0x5b, 0xd0, 0x94, 0x57, 0xa0, 0x59, + 0x76, 0x6c, 0xaa, 0xf9, 0xec, 0x37, 0x08, 0xe3, 0xc9, 0x2d, 0xc2, 0x85, 0x95, 0x08, 0xe3, 0xc9, + 0x4d, 0xc2, 0xdf, 0x41, 0xf4, 0xae, 0x21, 0x96, 0xd1, 0xc3, 0x43, 0x4c, 0x4d, 0xa2, 0x20, 0x21, + 0x58, 0xfd, 0x08, 0x41, 0x8d, 0x72, 0x5d, 0x8e, 0x89, 0x0e, 0x03, 0x1e, 0xf4, 0x25, 0x28, 0x63, + 0xda, 0x73, 0xa9, 0x65, 0xd3, 0xbe, 0x31, 0x22, 0x9e, 0xed, 0x5a, 0x06, 0x23, 0xa6, 0x4b, 0x2d, + 0xa6, 0x14, 0xb7, 0xa5, 0xdd, 0xb4, 0x5e, 0x8e, 0xf1, 0x53, 0x01, 0xb7, 0x03, 0x14, 0x95, 0x61, + 0x6d, 0x80, 0x87, 0x9c, 0x58, 0x4a, 0x69, 0x5b, 0xda, 0xcd, 0xe8, 0xe1, 0x6a, 0xe7, 0x4f, 0x09, + 0xe4, 0x46, 0xfc, 0x6e, 0xd4, 0x89, 0xe9, 0x7a, 0x16, 0xca, 0x41, 0x32, 0x9c, 0x05, 0x69, 0x3d, + 0x69, 0x5b, 0xa8, 0x0d, 0xd9, 0xf0, 0xc5, 0x8e, 0x1d, 0x77, 0x4c, 0x79, 0x30, 0x01, 0x3e, 0x3a, + 0x9f, 0x8d, 0x80, 0xa4, 0x26, 0x38, 0xd0, 0x73, 0x58, 0x63, 0x1c, 0xf3, 0x31, 0x13, 0xd3, 0x21, + 0x77, 0xf0, 0x69, 0x75, 0x6e, 0xac, 0x55, 0xe7, 0xf7, 0xd5, 0x16, 0xee, 0x7a, 0x18, 0x86, 0x1e, + 0xc0, 0x3a, 0x9f, 0x18, 0x03, 0xcc, 0x06, 0xe1, 0xb4, 0x58, 0xe3, 0x93, 0x97, 0x98, 0x0d, 0x76, + 0xfe, 0x48, 0x41, 0xbe, 0x1b, 0x95, 0xe1, 0x96, 0x94, 0x9e, 0xc5, 0xea, 0x49, 0xa1, 0xfe, 0x78, + 0x41, 0x7d, 0x8e, 0x61, 0x4e, 0xfc, 0x5b, 0xc8, 0x33, 0x1e, 0xce, 0xb9, 0xb0, 0x28, 0xa9, 0xff, + 0x54, 0x94, 0x2c, 0xe3, 0x62, 0x20, 0x86, 0x55, 0x59, 0x28, 0x75, 0x7a, 0x05, 0xa5, 0xd6, 0xe0, + 0x93, 0xe9, 0xb1, 0x31, 0x5d, 0x67, 0x34, 0x24, 0xe2, 0x32, 0x70, 0xdb, 0x21, 0xf1, 0xf9, 0xb9, + 0x23, 0x6a, 0x53, 0x89, 0x1d, 0xeb, 0xb1, 0x5f, 0xc7, 0x76, 0x48, 0x74, 0x8e, 0xbe, 0x80, 0xd2, + 0x98, 0xce, 0x0c, 0xe0, 0xa8, 0x03, 0x62, 0x76, 0xea, 0x68, 0x16, 0xeb, 0x88, 0x6e, 0xa0, 0x67, + 0xf0, 0x30, 0xe0, 0x24, 0x56, 0x58, 0x2f, 0x76, 0x41, 0xc8, 0x28, 0x8e, 0x14, 0x33, 0x53, 0x57, + 0x22, 0x1f, 0x51, 0x8c, 0xb6, 0xef, 0x11, 0xc4, 0xef, 0xfc, 0x9c, 0x04, 0x79, 0xe6, 0x8e, 0x05, + 0xed, 0xac, 0x42, 0x71, 0x9a, 0x91, 0x27, 0x6c, 0x46, 0xdc, 0xdf, 0xc2, 0xf8, 0x7a, 0xeb, 0x34, + 0x0b, 0x6d, 0x41, 0xc6, 0x7f, 0x09, 0x10, 0x87, 0x78, 0xe1, 0xe7, 0x4b, 0xbc, 0xfe, 0x5f, 0xb5, + 0x72, 0xe7, 0x77, 0x09, 0xee, 0xb5, 0x87, 0x98, 0x0d, 0x6e, 0x39, 0xd7, 0x08, 0xd2, 0x7e, 0x57, + 0x45, 0x92, 0x69, 0x5d, 0x3c, 0x2f, 0x6e, 0x24, 0xb5, 0x82, 0x33, 0xf5, 0x19, 0x14, 0xce, 0xf1, + 0xd0, 0xb6, 0x66, 0xbf, 0x19, 0xc2, 0x7b, 0x28, 0xc7, 0x40, 0x38, 0xc1, 0x9f, 0xfc, 0x00, 0xe5, + 0x9b, 0x2f, 0x33, 0x52, 0xa0, 0xd4, 0xd1, 0x6b, 0xad, 0xf6, 0x0b, 0x55, 0x37, 0xb4, 0x96, 0x71, + 0xaa, 0x9f, 0x1c, 0xe9, 0x6a, 0xbb, 0x2d, 0x27, 0x50, 0x11, 0xf2, 0x31, 0xf2, 0xa2, 0xa6, 0x35, + 0xd5, 0x86, 0x2c, 0xa1, 0x12, 0xc8, 0x0d, 0xb5, 0xa9, 0x1e, 0xd5, 0x3a, 0xda, 0x49, 0xcb, 0xf8, + 0xa6, 0xab, 0x76, 0x55, 0x39, 0x89, 0x1e, 0x40, 0x71, 0xc6, 0x5a, 0x3f, 0x39, 0x3e, 0x6d, 0xaa, + 0x1d, 0x55, 0x4e, 0x6d, 0xa5, 0x7f, 0xfa, 0xad, 0x92, 0x78, 0xf2, 0xab, 0x04, 0xf7, 0x6f, 0xbc, + 0xcd, 0xe8, 0x21, 0x28, 0xb5, 0x7a, 0xbd, 0x7b, 0xdc, 0x6d, 0xd6, 0x3a, 0x5a, 0xeb, 0xc8, 0xd0, + 0xd5, 0x86, 0x7a, 0x7c, 0xea, 0xb3, 0x84, 0x3b, 0xe8, 0xb6, 0x0e, 0x4f, 0x5a, 0x0d, 0x1f, 0x0a, + 0xb4, 0x24, 0xb4, 0x09, 0xf7, 0xa7, 0xc6, 0xd9, 0x1d, 0x27, 0xd1, 0x06, 0x64, 0x02, 0x48, 0x6d, + 0xc8, 0x29, 0x94, 0x85, 0xbb, 0xf5, 0x66, 0x4d, 0x3b, 0xae, 0x1d, 0x36, 0x55, 0x39, 0x8d, 0xee, + 0xc1, 0xba, 0x58, 0xaa, 0x0d, 0xf9, 0x4e, 0xb0, 0xaf, 0xc3, 0xe6, 0xdb, 0xcb, 0x8a, 0xf4, 0xee, + 0xb2, 0x22, 0xfd, 0x73, 0x59, 0x91, 0x7e, 0xb9, 0xaa, 0x24, 0xde, 0x5d, 0x55, 0x12, 0x7f, 0x5d, + 0x55, 0x12, 0xaf, 0x0e, 0x66, 0x5a, 0x12, 0x7c, 0xfc, 0xec, 0x35, 0x71, 0x8f, 0xed, 0x87, 0x7f, + 0x0c, 0xce, 0x0f, 0x0e, 0xf6, 0x27, 0xd3, 0xbf, 0x07, 0xa2, 0x45, 0xbd, 0x35, 0xf1, 0x69, 0xff, + 0xf4, 0xdf, 0x00, 0x00, 0x00, 0xff, 0xff, 0xb0, 0xdb, 0x16, 0xf1, 0x3e, 0x0c, 0x00, 0x00, +} + +func (m *HostZone) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *HostZone) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *HostZone) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Halted { + i-- + if m.Halted { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x1 + i-- + dAtA[i] = 0xa0 + } + if m.UnbondingPeriodSeconds != 0 { + i = encodeVarintStaketia(dAtA, i, uint64(m.UnbondingPeriodSeconds)) + i-- + dAtA[i] = 0x1 + i-- + dAtA[i] = 0x98 + } + { + size := m.DelegatedBalance.Size() + i -= size + if _, err := m.DelegatedBalance.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintStaketia(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1 + i-- + dAtA[i] = 0x92 + { + size := m.MaxInnerRedemptionRate.Size() + i -= size + if _, err := m.MaxInnerRedemptionRate.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintStaketia(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1 + i-- + dAtA[i] = 0x8a + { + size := m.MinInnerRedemptionRate.Size() + i -= size + if _, err := m.MinInnerRedemptionRate.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintStaketia(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1 + i-- + dAtA[i] = 0x82 + { + size := m.MaxRedemptionRate.Size() + i -= size + if _, err := m.MaxRedemptionRate.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintStaketia(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x7a + { + size := m.MinRedemptionRate.Size() + i -= size + if _, err := m.MinRedemptionRate.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintStaketia(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x72 + { + size := m.RedemptionRate.Size() + i -= size + if _, err := m.RedemptionRate.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintStaketia(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x6a + { + size := m.LastRedemptionRate.Size() + i -= size + if _, err := m.LastRedemptionRate.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintStaketia(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x62 + if len(m.SafeAddressOnStride) > 0 { + i -= len(m.SafeAddressOnStride) + copy(dAtA[i:], m.SafeAddressOnStride) + i = encodeVarintStaketia(dAtA, i, uint64(len(m.SafeAddressOnStride))) + i-- + dAtA[i] = 0x5a + } + if len(m.OperatorAddressOnStride) > 0 { + i -= len(m.OperatorAddressOnStride) + copy(dAtA[i:], m.OperatorAddressOnStride) + i = encodeVarintStaketia(dAtA, i, uint64(len(m.OperatorAddressOnStride))) + i-- + dAtA[i] = 0x52 + } + if len(m.ClaimAddress) > 0 { + i -= len(m.ClaimAddress) + copy(dAtA[i:], m.ClaimAddress) + i = encodeVarintStaketia(dAtA, i, uint64(len(m.ClaimAddress))) + i-- + dAtA[i] = 0x4a + } + if len(m.RedemptionAddress) > 0 { + i -= len(m.RedemptionAddress) + copy(dAtA[i:], m.RedemptionAddress) + i = encodeVarintStaketia(dAtA, i, uint64(len(m.RedemptionAddress))) + i-- + dAtA[i] = 0x42 + } + if len(m.DepositAddress) > 0 { + i -= len(m.DepositAddress) + copy(dAtA[i:], m.DepositAddress) + i = encodeVarintStaketia(dAtA, i, uint64(len(m.DepositAddress))) + i-- + dAtA[i] = 0x3a + } + if len(m.RewardAddress) > 0 { + i -= len(m.RewardAddress) + copy(dAtA[i:], m.RewardAddress) + i = encodeVarintStaketia(dAtA, i, uint64(len(m.RewardAddress))) + i-- + dAtA[i] = 0x32 + } + if len(m.DelegationAddress) > 0 { + i -= len(m.DelegationAddress) + copy(dAtA[i:], m.DelegationAddress) + i = encodeVarintStaketia(dAtA, i, uint64(len(m.DelegationAddress))) + i-- + dAtA[i] = 0x2a + } + if len(m.TransferChannelId) > 0 { + i -= len(m.TransferChannelId) + copy(dAtA[i:], m.TransferChannelId) + i = encodeVarintStaketia(dAtA, i, uint64(len(m.TransferChannelId))) + i-- + dAtA[i] = 0x22 + } + if len(m.NativeTokenIbcDenom) > 0 { + i -= len(m.NativeTokenIbcDenom) + copy(dAtA[i:], m.NativeTokenIbcDenom) + i = encodeVarintStaketia(dAtA, i, uint64(len(m.NativeTokenIbcDenom))) + i-- + dAtA[i] = 0x1a + } + if len(m.NativeTokenDenom) > 0 { + i -= len(m.NativeTokenDenom) + copy(dAtA[i:], m.NativeTokenDenom) + i = encodeVarintStaketia(dAtA, i, uint64(len(m.NativeTokenDenom))) + i-- + dAtA[i] = 0x12 + } + if len(m.ChainId) > 0 { + i -= len(m.ChainId) + copy(dAtA[i:], m.ChainId) + i = encodeVarintStaketia(dAtA, i, uint64(len(m.ChainId))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *DelegationRecord) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *DelegationRecord) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *DelegationRecord) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.TxHash) > 0 { + i -= len(m.TxHash) + copy(dAtA[i:], m.TxHash) + i = encodeVarintStaketia(dAtA, i, uint64(len(m.TxHash))) + i-- + dAtA[i] = 0x22 + } + if m.Status != 0 { + i = encodeVarintStaketia(dAtA, i, uint64(m.Status)) + i-- + dAtA[i] = 0x18 + } + { + size := m.NativeAmount.Size() + i -= size + if _, err := m.NativeAmount.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintStaketia(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + if m.Id != 0 { + i = encodeVarintStaketia(dAtA, i, uint64(m.Id)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *UnbondingRecord) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *UnbondingRecord) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *UnbondingRecord) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.UnbondedTokenSweepTxHash) > 0 { + i -= len(m.UnbondedTokenSweepTxHash) + copy(dAtA[i:], m.UnbondedTokenSweepTxHash) + i = encodeVarintStaketia(dAtA, i, uint64(len(m.UnbondedTokenSweepTxHash))) + i-- + dAtA[i] = 0x3a + } + if len(m.UndelegationTxHash) > 0 { + i -= len(m.UndelegationTxHash) + copy(dAtA[i:], m.UndelegationTxHash) + i = encodeVarintStaketia(dAtA, i, uint64(len(m.UndelegationTxHash))) + i-- + dAtA[i] = 0x32 + } + if m.UnbondingCompletionTimeSeconds != 0 { + i = encodeVarintStaketia(dAtA, i, uint64(m.UnbondingCompletionTimeSeconds)) + i-- + dAtA[i] = 0x28 + } + { + size := m.NativeAmount.Size() + i -= size + if _, err := m.NativeAmount.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintStaketia(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x22 + { + size := m.StTokenAmount.Size() + i -= size + if _, err := m.StTokenAmount.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintStaketia(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + if m.Status != 0 { + i = encodeVarintStaketia(dAtA, i, uint64(m.Status)) + i-- + dAtA[i] = 0x10 + } + if m.Id != 0 { + i = encodeVarintStaketia(dAtA, i, uint64(m.Id)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *RedemptionRecord) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *RedemptionRecord) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *RedemptionRecord) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size := m.NativeAmount.Size() + i -= size + if _, err := m.NativeAmount.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintStaketia(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x22 + { + size := m.StTokenAmount.Size() + i -= size + if _, err := m.StTokenAmount.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintStaketia(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + if len(m.Redeemer) > 0 { + i -= len(m.Redeemer) + copy(dAtA[i:], m.Redeemer) + i = encodeVarintStaketia(dAtA, i, uint64(len(m.Redeemer))) + i-- + dAtA[i] = 0x12 + } + if m.UnbondingRecordId != 0 { + i = encodeVarintStaketia(dAtA, i, uint64(m.UnbondingRecordId)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func (m *SlashRecord) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *SlashRecord) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *SlashRecord) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.ValidatorAddress) > 0 { + i -= len(m.ValidatorAddress) + copy(dAtA[i:], m.ValidatorAddress) + i = encodeVarintStaketia(dAtA, i, uint64(len(m.ValidatorAddress))) + i-- + dAtA[i] = 0x22 + } + { + size := m.NativeAmount.Size() + i -= size + if _, err := m.NativeAmount.MarshalTo(dAtA[i:]); err != nil { + return 0, err + } + i = encodeVarintStaketia(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + if m.Time != 0 { + i = encodeVarintStaketia(dAtA, i, uint64(m.Time)) + i-- + dAtA[i] = 0x10 + } + if m.Id != 0 { + i = encodeVarintStaketia(dAtA, i, uint64(m.Id)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func encodeVarintStaketia(dAtA []byte, offset int, v uint64) int { + offset -= sovStaketia(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *HostZone) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.ChainId) + if l > 0 { + n += 1 + l + sovStaketia(uint64(l)) + } + l = len(m.NativeTokenDenom) + if l > 0 { + n += 1 + l + sovStaketia(uint64(l)) + } + l = len(m.NativeTokenIbcDenom) + if l > 0 { + n += 1 + l + sovStaketia(uint64(l)) + } + l = len(m.TransferChannelId) + if l > 0 { + n += 1 + l + sovStaketia(uint64(l)) + } + l = len(m.DelegationAddress) + if l > 0 { + n += 1 + l + sovStaketia(uint64(l)) + } + l = len(m.RewardAddress) + if l > 0 { + n += 1 + l + sovStaketia(uint64(l)) + } + l = len(m.DepositAddress) + if l > 0 { + n += 1 + l + sovStaketia(uint64(l)) + } + l = len(m.RedemptionAddress) + if l > 0 { + n += 1 + l + sovStaketia(uint64(l)) + } + l = len(m.ClaimAddress) + if l > 0 { + n += 1 + l + sovStaketia(uint64(l)) + } + l = len(m.OperatorAddressOnStride) + if l > 0 { + n += 1 + l + sovStaketia(uint64(l)) + } + l = len(m.SafeAddressOnStride) + if l > 0 { + n += 1 + l + sovStaketia(uint64(l)) + } + l = m.LastRedemptionRate.Size() + n += 1 + l + sovStaketia(uint64(l)) + l = m.RedemptionRate.Size() + n += 1 + l + sovStaketia(uint64(l)) + l = m.MinRedemptionRate.Size() + n += 1 + l + sovStaketia(uint64(l)) + l = m.MaxRedemptionRate.Size() + n += 1 + l + sovStaketia(uint64(l)) + l = m.MinInnerRedemptionRate.Size() + n += 2 + l + sovStaketia(uint64(l)) + l = m.MaxInnerRedemptionRate.Size() + n += 2 + l + sovStaketia(uint64(l)) + l = m.DelegatedBalance.Size() + n += 2 + l + sovStaketia(uint64(l)) + if m.UnbondingPeriodSeconds != 0 { + n += 2 + sovStaketia(uint64(m.UnbondingPeriodSeconds)) + } + if m.Halted { + n += 3 + } + return n +} + +func (m *DelegationRecord) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Id != 0 { + n += 1 + sovStaketia(uint64(m.Id)) + } + l = m.NativeAmount.Size() + n += 1 + l + sovStaketia(uint64(l)) + if m.Status != 0 { + n += 1 + sovStaketia(uint64(m.Status)) + } + l = len(m.TxHash) + if l > 0 { + n += 1 + l + sovStaketia(uint64(l)) + } + return n +} + +func (m *UnbondingRecord) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Id != 0 { + n += 1 + sovStaketia(uint64(m.Id)) + } + if m.Status != 0 { + n += 1 + sovStaketia(uint64(m.Status)) + } + l = m.StTokenAmount.Size() + n += 1 + l + sovStaketia(uint64(l)) + l = m.NativeAmount.Size() + n += 1 + l + sovStaketia(uint64(l)) + if m.UnbondingCompletionTimeSeconds != 0 { + n += 1 + sovStaketia(uint64(m.UnbondingCompletionTimeSeconds)) + } + l = len(m.UndelegationTxHash) + if l > 0 { + n += 1 + l + sovStaketia(uint64(l)) + } + l = len(m.UnbondedTokenSweepTxHash) + if l > 0 { + n += 1 + l + sovStaketia(uint64(l)) + } + return n +} + +func (m *RedemptionRecord) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.UnbondingRecordId != 0 { + n += 1 + sovStaketia(uint64(m.UnbondingRecordId)) + } + l = len(m.Redeemer) + if l > 0 { + n += 1 + l + sovStaketia(uint64(l)) + } + l = m.StTokenAmount.Size() + n += 1 + l + sovStaketia(uint64(l)) + l = m.NativeAmount.Size() + n += 1 + l + sovStaketia(uint64(l)) + return n +} + +func (m *SlashRecord) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Id != 0 { + n += 1 + sovStaketia(uint64(m.Id)) + } + if m.Time != 0 { + n += 1 + sovStaketia(uint64(m.Time)) + } + l = m.NativeAmount.Size() + n += 1 + l + sovStaketia(uint64(l)) + l = len(m.ValidatorAddress) + if l > 0 { + n += 1 + l + sovStaketia(uint64(l)) + } + return n +} + +func sovStaketia(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozStaketia(x uint64) (n int) { + return sovStaketia(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *HostZone) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowStaketia + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: HostZone: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: HostZone: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ChainId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowStaketia + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthStaketia + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthStaketia + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ChainId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field NativeTokenDenom", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowStaketia + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthStaketia + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthStaketia + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.NativeTokenDenom = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field NativeTokenIbcDenom", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowStaketia + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthStaketia + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthStaketia + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.NativeTokenIbcDenom = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field TransferChannelId", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowStaketia + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthStaketia + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthStaketia + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.TransferChannelId = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 5: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field DelegationAddress", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowStaketia + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthStaketia + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthStaketia + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.DelegationAddress = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field RewardAddress", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowStaketia + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthStaketia + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthStaketia + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.RewardAddress = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 7: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field DepositAddress", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowStaketia + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthStaketia + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthStaketia + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.DepositAddress = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 8: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field RedemptionAddress", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowStaketia + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthStaketia + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthStaketia + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.RedemptionAddress = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 9: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ClaimAddress", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowStaketia + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthStaketia + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthStaketia + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ClaimAddress = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 10: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field OperatorAddressOnStride", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowStaketia + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthStaketia + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthStaketia + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.OperatorAddressOnStride = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 11: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field SafeAddressOnStride", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowStaketia + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthStaketia + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthStaketia + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.SafeAddressOnStride = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 12: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field LastRedemptionRate", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowStaketia + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthStaketia + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthStaketia + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.LastRedemptionRate.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 13: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field RedemptionRate", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowStaketia + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthStaketia + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthStaketia + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.RedemptionRate.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 14: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field MinRedemptionRate", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowStaketia + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthStaketia + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthStaketia + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.MinRedemptionRate.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 15: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field MaxRedemptionRate", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowStaketia + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthStaketia + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthStaketia + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.MaxRedemptionRate.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 16: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field MinInnerRedemptionRate", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowStaketia + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthStaketia + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthStaketia + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.MinInnerRedemptionRate.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 17: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field MaxInnerRedemptionRate", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowStaketia + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthStaketia + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthStaketia + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.MaxInnerRedemptionRate.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 18: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field DelegatedBalance", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowStaketia + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthStaketia + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthStaketia + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.DelegatedBalance.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 19: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field UnbondingPeriodSeconds", wireType) + } + m.UnbondingPeriodSeconds = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowStaketia + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.UnbondingPeriodSeconds |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 20: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Halted", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowStaketia + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + m.Halted = bool(v != 0) + default: + iNdEx = preIndex + skippy, err := skipStaketia(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthStaketia + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *DelegationRecord) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowStaketia + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: DelegationRecord: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: DelegationRecord: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Id", wireType) + } + m.Id = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowStaketia + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Id |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field NativeAmount", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowStaketia + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthStaketia + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthStaketia + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.NativeAmount.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Status", wireType) + } + m.Status = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowStaketia + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Status |= DelegationRecordStatus(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field TxHash", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowStaketia + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthStaketia + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthStaketia + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.TxHash = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipStaketia(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthStaketia + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *UnbondingRecord) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowStaketia + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: UnbondingRecord: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: UnbondingRecord: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Id", wireType) + } + m.Id = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowStaketia + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Id |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Status", wireType) + } + m.Status = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowStaketia + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Status |= UnbondingRecordStatus(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field StTokenAmount", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowStaketia + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthStaketia + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthStaketia + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.StTokenAmount.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field NativeAmount", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowStaketia + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthStaketia + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthStaketia + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.NativeAmount.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 5: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field UnbondingCompletionTimeSeconds", wireType) + } + m.UnbondingCompletionTimeSeconds = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowStaketia + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.UnbondingCompletionTimeSeconds |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field UndelegationTxHash", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowStaketia + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthStaketia + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthStaketia + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.UndelegationTxHash = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 7: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field UnbondedTokenSweepTxHash", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowStaketia + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthStaketia + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthStaketia + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.UnbondedTokenSweepTxHash = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipStaketia(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthStaketia + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *RedemptionRecord) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowStaketia + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: RedemptionRecord: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: RedemptionRecord: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field UnbondingRecordId", wireType) + } + m.UnbondingRecordId = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowStaketia + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.UnbondingRecordId |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Redeemer", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowStaketia + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthStaketia + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthStaketia + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Redeemer = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field StTokenAmount", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowStaketia + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthStaketia + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthStaketia + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.StTokenAmount.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field NativeAmount", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowStaketia + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthStaketia + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthStaketia + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.NativeAmount.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipStaketia(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthStaketia + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *SlashRecord) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowStaketia + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: SlashRecord: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: SlashRecord: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Id", wireType) + } + m.Id = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowStaketia + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Id |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Time", wireType) + } + m.Time = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowStaketia + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Time |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field NativeAmount", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowStaketia + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthStaketia + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthStaketia + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.NativeAmount.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ValidatorAddress", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowStaketia + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthStaketia + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthStaketia + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ValidatorAddress = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipStaketia(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthStaketia + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipStaketia(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowStaketia + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowStaketia + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowStaketia + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthStaketia + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupStaketia + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthStaketia + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthStaketia = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowStaketia = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupStaketia = fmt.Errorf("proto: unexpected end of group") +) \ No newline at end of file diff --git a/x/staketia/types/celestia.go b/x/staketia/types/celestia.go index 8883768bfa..1511248adf 100644 --- a/x/staketia/types/celestia.go +++ b/x/staketia/types/celestia.go @@ -16,5 +16,11 @@ const ( SafeAddressOnStride = "stride18p7xg4hj2u3zpk0v9gq68pjyuuua5wa387sjjc" // S3 OperatorAddressOnStride = "stride1ghhu67ttgmxrsyxljfl2tysyayswklvxs7pepw" // OP-STRIDE - CelestiaUnbondingPeriodSeconds = uint64(21 * 24 * 60 * 60) // 21 days + CelestiaUnbondingPeriodDays = 21 + CelestiaUnbondingPeriodSeconds = uint64(CelestiaUnbondingPeriodDays * 24 * 60 * 60) // 21 days + + CelestiaBechPrefix = "celestia" ) + +// The connection ID is stored as a var so it can be overriden in tests +var CelestiaConnectionId = "connection-125" diff --git a/x/staketia/types/errors.go b/x/staketia/types/errors.go index 0c8c35c0b9..715086e0bd 100644 --- a/x/staketia/types/errors.go +++ b/x/staketia/types/errors.go @@ -29,4 +29,5 @@ var ( ErrDivisionByZero = errorsmod.Register(ModuleName, 1924, "division by zero") ErrInvalidRecordType = errorsmod.Register(ModuleName, 1925, "invalid record type") ErrInvalidGenesisRecords = errorsmod.Register(ModuleName, 1926, "invalid records during genesis") + ErrRedemptionsDisabled = errorsmod.Register(ModuleName, 1927, "redemptions are no longer enabled with staketia") ) diff --git a/x/staketia/types/expected_keepers.go b/x/staketia/types/expected_keepers.go index c39d87c3cf..067153894c 100644 --- a/x/staketia/types/expected_keepers.go +++ b/x/staketia/types/expected_keepers.go @@ -6,6 +6,9 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" transfertypes "github.com/cosmos/ibc-go/v7/modules/apps/transfer/types" + + recordtypes "github.com/Stride-Labs/stride/v24/x/records/types" + stakeibctypes "github.com/Stride-Labs/stride/v24/x/stakeibc/types" ) // Required AccountKeeper functions @@ -41,3 +44,19 @@ type RatelimitKeeper interface { type ICAOracleKeeper interface { QueueMetricUpdate(ctx sdk.Context, key, value, metricType, attributes string) } + +// Required StakeibcKeeper functions +type StakeibcKeeper interface { + GetHostZone(ctx sdk.Context, chainId string) (val stakeibctypes.HostZone, found bool) + GetActiveHostZone(ctx sdk.Context, chainId string) (hostZone stakeibctypes.HostZone, err error) + SetHostZone(ctx sdk.Context, hostZone stakeibctypes.HostZone) + RedeemStake(ctx sdk.Context, msg *stakeibctypes.MsgRedeemStake) (*stakeibctypes.MsgRedeemStakeResponse, error) + EnableRedemptions(ctx sdk.Context, chainId string) error + RegisterHostZone(ctx sdk.Context, msg *stakeibctypes.MsgRegisterHostZone) (*stakeibctypes.MsgRegisterHostZoneResponse, error) +} + +// Required RecordsKeeper functions +type RecordsKeeper interface { + GetAllDepositRecord(ctx sdk.Context) (list []recordtypes.DepositRecord) + SetDepositRecord(ctx sdk.Context, depositRecord recordtypes.DepositRecord) +} diff --git a/x/staketia/types/genesis.go b/x/staketia/types/genesis.go index 7baba778e4..17ecb4c4b1 100644 --- a/x/staketia/types/genesis.go +++ b/x/staketia/types/genesis.go @@ -2,7 +2,6 @@ package types import ( sdkmath "cosmossdk.io/math" - sdk "github.com/cosmos/cosmos-sdk/types" ) // DefaultGenesis returns the default genesis state @@ -30,14 +29,8 @@ func DefaultGenesis() *GenesisState { SafeAddressOnStride: SafeAddressOnStride, OperatorAddressOnStride: OperatorAddressOnStride, - RedemptionRate: sdk.OneDec(), - LastRedemptionRate: sdk.OneDec(), - MinRedemptionRate: sdk.MustNewDecFromStr("0.95"), - MaxRedemptionRate: sdk.MustNewDecFromStr("1.1"), - MinInnerRedemptionRate: sdk.MustNewDecFromStr("0.95"), - MaxInnerRedemptionRate: sdk.MustNewDecFromStr("1.1"), - DelegatedBalance: sdkmath.ZeroInt(), - Halted: false, + RemainingDelegatedBalance: sdkmath.ZeroInt(), + Halted: false, }, UnbondingRecords: []UnbondingRecord{ { diff --git a/x/staketia/types/host_zone.go b/x/staketia/types/host_zone.go index c5b9ee25e1..d50b833b40 100644 --- a/x/staketia/types/host_zone.go +++ b/x/staketia/types/host_zone.go @@ -76,14 +76,6 @@ func (h HostZone) ValidateGenesis() error { return errorsmod.Wrapf(err, "invalid safe address") } - // Validate the redemption rate bounds are set properly - if !h.RedemptionRate.IsPositive() { - return ErrInvalidHostZone.Wrap("redemption rate must be positive") - } - if err := h.ValidateRedemptionRateBoundsInitalized(); err != nil { - return err - } - // Validate unbonding period is set if h.UnbondingPeriodSeconds == 0 { return ErrInvalidHostZone.Wrap("unbonding period must be set") @@ -91,35 +83,3 @@ func (h HostZone) ValidateGenesis() error { return nil } - -// Verify the redemption rate bounds are set properly on the host zone -func (h HostZone) ValidateRedemptionRateBoundsInitalized() error { - // Validate outer bounds are set - if h.MinRedemptionRate.IsNil() || !h.MinRedemptionRate.IsPositive() { - return ErrInvalidRedemptionRateBounds.Wrapf("min outer redemption rate bound not set") - } - if h.MaxRedemptionRate.IsNil() || !h.MaxRedemptionRate.IsPositive() { - return ErrInvalidRedemptionRateBounds.Wrapf("max outer redemption rate bound not set") - } - - // Validate inner bounds set - if h.MinInnerRedemptionRate.IsNil() || !h.MinInnerRedemptionRate.IsPositive() { - return ErrInvalidRedemptionRateBounds.Wrapf("min inner redemption rate bound not set") - } - if h.MaxInnerRedemptionRate.IsNil() || !h.MaxInnerRedemptionRate.IsPositive() { - return ErrInvalidRedemptionRateBounds.Wrapf("max inner redemption rate bound not set") - } - - // Validate inner bounds are within outer bounds - if h.MinInnerRedemptionRate.LT(h.MinRedemptionRate) { - return ErrInvalidRedemptionRateBounds.Wrapf("min inner redemption rate bound outside of min outer bound") - } - if h.MaxInnerRedemptionRate.GT(h.MaxRedemptionRate) { - return ErrInvalidRedemptionRateBounds.Wrapf("max inner redemption rate bound outside of max outer bound") - } - if h.MinInnerRedemptionRate.GT(h.MaxInnerRedemptionRate) { - return ErrInvalidRedemptionRateBounds.Wrapf("min inner redemption rate greater than max inner bound") - } - - return nil -} diff --git a/x/staketia/types/host_zone_test.go b/x/staketia/types/host_zone_test.go index 64175b4679..f456145b79 100644 --- a/x/staketia/types/host_zone_test.go +++ b/x/staketia/types/host_zone_test.go @@ -3,7 +3,6 @@ package types_test import ( "testing" - sdk "github.com/cosmos/cosmos-sdk/types" transfertypes "github.com/cosmos/ibc-go/v7/modules/apps/transfer/types" "github.com/stretchr/testify/require" @@ -52,14 +51,6 @@ func fillDefaultHostZone(hostZone types.HostZone) types.HostZone { hostZone.OperatorAddressOnStride = fillDefaultValue(hostZone.OperatorAddressOnStride, validAddress) hostZone.SafeAddressOnStride = fillDefaultValue(hostZone.SafeAddressOnStride, validAddress) - if hostZone.RedemptionRate.IsNil() { - hostZone.RedemptionRate = sdk.OneDec() - hostZone.MinRedemptionRate = sdk.MustNewDecFromStr("0.8") - hostZone.MinInnerRedemptionRate = sdk.MustNewDecFromStr("0.9") - hostZone.MaxInnerRedemptionRate = sdk.MustNewDecFromStr("1.1") - hostZone.MaxRedemptionRate = sdk.MustNewDecFromStr("1.2") - } - if hostZone.UnbondingPeriodSeconds == UninitializedInt { hostZone.UnbondingPeriodSeconds = 0 // invalid } else { @@ -200,22 +191,6 @@ func TestValidateHostZoneGenesis(t *testing.T) { }, expectedError: "invalid safe address", }, - { - name: "invalid redemption rate", - hostZone: types.HostZone{ - RedemptionRate: sdk.OneDec().Neg(), - }, - expectedError: "redemption rate must be positive", - }, - { - name: "invalid redemption rate bounds", - hostZone: types.HostZone{ - RedemptionRate: sdk.OneDec(), - MinRedemptionRate: sdk.MustNewDecFromStr("1.1"), - MinInnerRedemptionRate: sdk.MustNewDecFromStr("0.9"), - }, - expectedError: "invalid host zone redemption rate inner bounds", - }, { name: "missing unbonding period", hostZone: types.HostZone{ @@ -238,111 +213,3 @@ func TestValidateHostZoneGenesis(t *testing.T) { }) } } - -func TestValidateRedemptionRateBoundsInitalized(t *testing.T) { - testCases := []struct { - name string - hostZone types.HostZone - valid bool - }{ - { - name: "valid bounds", - hostZone: types.HostZone{ - MinRedemptionRate: sdk.MustNewDecFromStr("0.8"), - MinInnerRedemptionRate: sdk.MustNewDecFromStr("0.9"), - RedemptionRate: sdk.MustNewDecFromStr("1.0"), - MaxInnerRedemptionRate: sdk.MustNewDecFromStr("1.1"), - MaxRedemptionRate: sdk.MustNewDecFromStr("1.2"), - }, - valid: true, - }, - { - name: "min outer negative", - hostZone: types.HostZone{ - MinRedemptionRate: sdk.MustNewDecFromStr("0.8").Neg(), - MinInnerRedemptionRate: sdk.MustNewDecFromStr("0.9"), - RedemptionRate: sdk.MustNewDecFromStr("1.0"), - MaxInnerRedemptionRate: sdk.MustNewDecFromStr("1.1"), - MaxRedemptionRate: sdk.MustNewDecFromStr("1.2"), - }, - valid: false, - }, - { - name: "min inner negative", - hostZone: types.HostZone{ - MinRedemptionRate: sdk.MustNewDecFromStr("0.8"), - MinInnerRedemptionRate: sdk.MustNewDecFromStr("0.9").Neg(), - RedemptionRate: sdk.MustNewDecFromStr("1.0"), - MaxInnerRedemptionRate: sdk.MustNewDecFromStr("1.1"), - MaxRedemptionRate: sdk.MustNewDecFromStr("1.2"), - }, - valid: false, - }, - { - name: "max inner negative", - hostZone: types.HostZone{ - MinRedemptionRate: sdk.MustNewDecFromStr("0.8"), - MinInnerRedemptionRate: sdk.MustNewDecFromStr("0.9"), - RedemptionRate: sdk.MustNewDecFromStr("1.0"), - MaxInnerRedemptionRate: sdk.MustNewDecFromStr("1.1").Neg(), - MaxRedemptionRate: sdk.MustNewDecFromStr("1.2"), - }, - valid: false, - }, - { - name: "max outer negative", - hostZone: types.HostZone{ - MinRedemptionRate: sdk.MustNewDecFromStr("0.8"), - MinInnerRedemptionRate: sdk.MustNewDecFromStr("0.9"), - RedemptionRate: sdk.MustNewDecFromStr("1.0"), - MaxInnerRedemptionRate: sdk.MustNewDecFromStr("1.1"), - MaxRedemptionRate: sdk.MustNewDecFromStr("1.2").Neg(), - }, - valid: false, - }, - { - name: "max inner outside outer", - hostZone: types.HostZone{ - MinRedemptionRate: sdk.MustNewDecFromStr("0.8"), - MinInnerRedemptionRate: sdk.MustNewDecFromStr("0.9"), - RedemptionRate: sdk.MustNewDecFromStr("1.0"), - MaxInnerRedemptionRate: sdk.MustNewDecFromStr("1.3"), // <-- - MaxRedemptionRate: sdk.MustNewDecFromStr("1.2"), - }, - valid: false, - }, - { - name: "min inner outside outer", - hostZone: types.HostZone{ - MinRedemptionRate: sdk.MustNewDecFromStr("0.8"), - MinInnerRedemptionRate: sdk.MustNewDecFromStr("0.7"), // <-- - RedemptionRate: sdk.MustNewDecFromStr("1.0"), - MaxInnerRedemptionRate: sdk.MustNewDecFromStr("1.1"), - MaxRedemptionRate: sdk.MustNewDecFromStr("1.2"), - }, - valid: false, - }, - { - name: "min inner greater than min outer", - hostZone: types.HostZone{ - MinRedemptionRate: sdk.MustNewDecFromStr("0.8"), - MinInnerRedemptionRate: sdk.MustNewDecFromStr("1.1"), // <-- - RedemptionRate: sdk.MustNewDecFromStr("1.0"), - MaxInnerRedemptionRate: sdk.MustNewDecFromStr("0.9"), // <-- - MaxRedemptionRate: sdk.MustNewDecFromStr("1.2"), - }, - valid: false, - }, - } - - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - err := tc.hostZone.ValidateRedemptionRateBoundsInitalized() - if tc.valid { - require.NoError(t, err, "no error expected") - } else { - require.ErrorIs(t, err, types.ErrInvalidRedemptionRateBounds) - } - }) - } -} diff --git a/x/staketia/types/msgs.go b/x/staketia/types/msgs.go index cbfc81cff8..e7d690c473 100644 --- a/x/staketia/types/msgs.go +++ b/x/staketia/types/msgs.go @@ -106,10 +106,11 @@ func (msg *MsgLiquidStake) ValidateBasic() error { // MsgRedeemStake // ---------------------------------------------- -func NewMsgRedeemStake(redeemer string, stTokenAmount sdkmath.Int) *MsgRedeemStake { +func NewMsgRedeemStake(redeemer string, stTokenAmount sdkmath.Int, receiver string) *MsgRedeemStake { return &MsgRedeemStake{ Redeemer: redeemer, StTokenAmount: stTokenAmount, + Receiver: receiver, } } @@ -145,6 +146,10 @@ func (msg *MsgRedeemStake) ValidateBasic() error { return errorsmod.Wrapf(ErrInvalidAmountBelowMinimum, "amount (%v) is below 0.1 stTIA minimum", msg.StTokenAmount) } + if msg.Receiver == "" { + return errorsmod.Wrapf(sdkerrors.ErrInvalidRequest, "receiver must be specified") + } + return nil } diff --git a/x/staketia/types/msgs_test.go b/x/staketia/types/msgs_test.go index 3539794c6f..ddc1843e02 100644 --- a/x/staketia/types/msgs_test.go +++ b/x/staketia/types/msgs_test.go @@ -92,6 +92,7 @@ func TestMsgRedeemStake_ValidateBasic(t *testing.T) { msg: types.MsgRedeemStake{ Redeemer: sample.AccAddress(), StTokenAmount: sdkmath.NewInt(1000000), + Receiver: "reciever", }, }, { @@ -99,6 +100,7 @@ func TestMsgRedeemStake_ValidateBasic(t *testing.T) { msg: types.MsgRedeemStake{ Redeemer: "invalid_address", StTokenAmount: sdkmath.NewInt(1000000), + Receiver: "reciever", }, err: sdkerrors.ErrInvalidAddress, }, @@ -107,9 +109,19 @@ func TestMsgRedeemStake_ValidateBasic(t *testing.T) { msg: types.MsgRedeemStake{ Redeemer: sample.AccAddress(), StTokenAmount: sdkmath.NewInt(20000), + Receiver: "reciever", }, err: types.ErrInvalidAmountBelowMinimum, }, + { + name: "invalid receiver", + msg: types.MsgRedeemStake{ + Redeemer: sample.AccAddress(), + StTokenAmount: sdkmath.NewInt(1000000), + Receiver: "", + }, + err: sdkerrors.ErrInvalidRequest, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -125,10 +137,10 @@ func TestMsgRedeemStake_ValidateBasic(t *testing.T) { func TestMsgRedeemStake_GetSignBytes(t *testing.T) { addr := "stride1v9jxgu33kfsgr5" - msg := types.NewMsgRedeemStake(addr, sdkmath.NewInt(1000000)) + msg := types.NewMsgRedeemStake(addr, sdkmath.NewInt(1000000), "receiver") res := msg.GetSignBytes() - expected := `{"type":"staketia/MsgRedeemStake","value":{"redeemer":"stride1v9jxgu33kfsgr5","st_token_amount":"1000000"}}` + expected := `{"type":"staketia/MsgRedeemStake","value":{"receiver":"receiver","redeemer":"stride1v9jxgu33kfsgr5","st_token_amount":"1000000"}}` require.Equal(t, expected, string(res)) } diff --git a/x/staketia/types/staketia.pb.go b/x/staketia/types/staketia.pb.go index b0e2f59ab5..d6dc62afa3 100644 --- a/x/staketia/types/staketia.pb.go +++ b/x/staketia/types/staketia.pb.go @@ -142,20 +142,8 @@ type HostZone struct { OperatorAddressOnStride string `protobuf:"bytes,10,opt,name=operator_address_on_stride,json=operatorAddressOnStride,proto3" json:"operator_address_on_stride,omitempty"` // admin address set upon host zone creation, on stride SafeAddressOnStride string `protobuf:"bytes,11,opt,name=safe_address_on_stride,json=safeAddressOnStride,proto3" json:"safe_address_on_stride,omitempty"` - // Previous redemption rate - LastRedemptionRate github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,12,opt,name=last_redemption_rate,json=lastRedemptionRate,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"last_redemption_rate"` - // Current redemption rate - RedemptionRate github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,13,opt,name=redemption_rate,json=redemptionRate,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"redemption_rate"` - // Min outer redemption rate - adjusted by governance - MinRedemptionRate github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,14,opt,name=min_redemption_rate,json=minRedemptionRate,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"min_redemption_rate"` - // Max outer redemption rate - adjusted by governance - MaxRedemptionRate github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,15,opt,name=max_redemption_rate,json=maxRedemptionRate,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"max_redemption_rate"` - // Min inner redemption rate - adjusted by controller - MinInnerRedemptionRate github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,16,opt,name=min_inner_redemption_rate,json=minInnerRedemptionRate,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"min_inner_redemption_rate"` - // Max inner redemption rate - adjusted by controller - MaxInnerRedemptionRate github_com_cosmos_cosmos_sdk_types.Dec `protobuf:"bytes,17,opt,name=max_inner_redemption_rate,json=maxInnerRedemptionRate,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Dec" json:"max_inner_redemption_rate"` // Total delegated balance on the host zone delegation account - DelegatedBalance github_com_cosmos_cosmos_sdk_types.Int `protobuf:"bytes,18,opt,name=delegated_balance,json=delegatedBalance,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Int" json:"delegated_balance"` + RemainingDelegatedBalance github_com_cosmos_cosmos_sdk_types.Int `protobuf:"bytes,18,opt,name=remaining_delegated_balance,json=remainingDelegatedBalance,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Int" json:"remaining_delegated_balance"` // The undelegation period for Celestia in days UnbondingPeriodSeconds uint64 `protobuf:"varint,19,opt,name=unbonding_period_seconds,json=unbondingPeriodSeconds,proto3" json:"unbonding_period_seconds,omitempty"` // Indicates whether the host zone has been halted @@ -581,78 +569,71 @@ func init() { func init() { proto.RegisterFile("stride/staketia/staketia.proto", fileDescriptor_d306d9365b78f7b2) } var fileDescriptor_d306d9365b78f7b2 = []byte{ - // 1121 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xd4, 0x57, 0xcf, 0x6f, 0x1a, 0xc7, - 0x17, 0x67, 0x81, 0xd8, 0xe4, 0xc5, 0xc0, 0x32, 0x10, 0xb2, 0xb6, 0x22, 0xe2, 0xaf, 0x0f, 0xf9, - 0x5a, 0x69, 0x8d, 0x2b, 0xa7, 0x87, 0x1e, 0xda, 0x44, 0x18, 0x36, 0xce, 0x4a, 0x18, 0xbb, 0x0b, - 0xf4, 0x90, 0x1e, 0x56, 0xc3, 0xee, 0x04, 0x56, 0x66, 0x67, 0xd1, 0xce, 0x60, 0x53, 0xa9, 0xf7, - 0x56, 0xea, 0xa5, 0x97, 0xfe, 0x05, 0xfd, 0x13, 0x9a, 0x3f, 0x22, 0x52, 0x2f, 0x69, 0x4e, 0x55, - 0x0f, 0x51, 0x65, 0xff, 0x23, 0xd5, 0xce, 0xfe, 0x00, 0x83, 0x2d, 0x94, 0x8a, 0x4b, 0x4f, 0xec, - 0xbc, 0xcf, 0x7b, 0x9f, 0xcf, 0xbc, 0xf7, 0x66, 0xf6, 0x2d, 0x50, 0x61, 0xdc, 0xb3, 0x2d, 0xb2, - 0xcf, 0x38, 0x3e, 0x23, 0xdc, 0xc6, 0xf1, 0x43, 0x75, 0xe4, 0xb9, 0xdc, 0x45, 0xf9, 0x00, 0xaf, - 0x46, 0xe6, 0xad, 0x4d, 0xd3, 0x65, 0x8e, 0xcb, 0x0c, 0x01, 0xef, 0x07, 0x8b, 0xc0, 0x77, 0xab, - 0xd4, 0x77, 0xfb, 0x6e, 0x60, 0xf7, 0x9f, 0x02, 0xeb, 0xce, 0x0f, 0x1b, 0x90, 0x79, 0xe9, 0x32, - 0xfe, 0xca, 0xa5, 0x04, 0x6d, 0x42, 0xc6, 0x1c, 0x60, 0x9b, 0x1a, 0xb6, 0xa5, 0x48, 0xdb, 0xd2, - 0xee, 0x5d, 0x7d, 0x5d, 0xac, 0x35, 0x0b, 0x7d, 0x0a, 0x88, 0x62, 0x6e, 0x9f, 0x13, 0x83, 0xbb, - 0x67, 0x84, 0x1a, 0x16, 0xa1, 0xae, 0xa3, 0x24, 0x85, 0x93, 0x1c, 0x20, 0x1d, 0x1f, 0x68, 0xf8, - 0x76, 0xf4, 0x14, 0xca, 0xd7, 0xbc, 0xed, 0x9e, 0x19, 0x46, 0xa4, 0x44, 0x44, 0x71, 0x26, 0x42, - 0xeb, 0x99, 0x41, 0x50, 0x15, 0x8a, 0xdc, 0xc3, 0x94, 0xbd, 0x26, 0x9e, 0x61, 0x0e, 0x30, 0xa5, - 0x64, 0xe8, 0x6f, 0x24, 0x2d, 0x22, 0x0a, 0x11, 0x54, 0x0f, 0x10, 0xcd, 0x42, 0x47, 0x80, 0x2c, - 0x32, 0x24, 0x7d, 0xcc, 0x6d, 0x97, 0x1a, 0xd8, 0xb2, 0x3c, 0xc2, 0x98, 0x72, 0xc7, 0x77, 0x3f, - 0x54, 0xde, 0xbf, 0xd9, 0x2b, 0x85, 0xe9, 0xd7, 0x02, 0xa4, 0xcd, 0x3d, 0x9b, 0xf6, 0xf5, 0xc2, - 0x34, 0x26, 0x04, 0xd0, 0x73, 0xc8, 0x79, 0xe4, 0x02, 0x7b, 0x56, 0x4c, 0xb2, 0xb6, 0x84, 0x24, - 0x1b, 0xf8, 0x47, 0x04, 0x35, 0xc8, 0x5b, 0x64, 0xe4, 0x32, 0x9b, 0xc7, 0x0c, 0xeb, 0x4b, 0x18, - 0x72, 0x61, 0x40, 0x44, 0x71, 0x04, 0xc8, 0x23, 0x16, 0x71, 0x46, 0xd7, 0x92, 0xc9, 0x2c, 0x4b, - 0x66, 0x1a, 0x13, 0x11, 0x7d, 0x05, 0x59, 0x73, 0x88, 0x6d, 0x27, 0xe6, 0xb8, 0xbb, 0x84, 0x63, - 0x43, 0xb8, 0x47, 0xe1, 0x5d, 0xd8, 0x72, 0x47, 0xc4, 0xc3, 0xdc, 0xf5, 0x22, 0x06, 0xc3, 0xa5, - 0x46, 0x70, 0xce, 0x14, 0x58, 0xc2, 0xf5, 0x20, 0x8a, 0x0d, 0xcd, 0x27, 0xb4, 0x2d, 0x02, 0xd1, - 0x31, 0x94, 0x19, 0x7e, 0x4d, 0x6e, 0xa0, 0xbc, 0xb7, 0x84, 0xb2, 0xe8, 0xc7, 0xcd, 0xd3, 0x51, - 0x28, 0x0d, 0x31, 0xe3, 0xc6, 0x4c, 0xc9, 0x3c, 0xcc, 0x89, 0xb2, 0x21, 0xc8, 0xbe, 0x7c, 0xfb, - 0xe1, 0x51, 0xe2, 0xaf, 0x0f, 0x8f, 0x1e, 0xf7, 0x6d, 0x3e, 0x18, 0xf7, 0xaa, 0xa6, 0xeb, 0x84, - 0x57, 0x21, 0xfc, 0xd9, 0x63, 0xd6, 0xd9, 0x3e, 0xff, 0x6e, 0x44, 0x58, 0xb5, 0x41, 0xcc, 0xf7, - 0x6f, 0xf6, 0x20, 0x94, 0x6e, 0x10, 0x53, 0x47, 0x3e, 0xb3, 0x1e, 0x13, 0xeb, 0x98, 0x13, 0x44, - 0x20, 0x3f, 0x2f, 0x95, 0x5d, 0x81, 0x54, 0xce, 0xbb, 0x2e, 0x33, 0x84, 0xa2, 0x63, 0xd3, 0x85, - 0xac, 0x72, 0x2b, 0x90, 0x2a, 0x38, 0x36, 0xd5, 0x17, 0xd5, 0xf0, 0x64, 0x41, 0x2d, 0xbf, 0x12, - 0x35, 0x3c, 0x99, 0x53, 0xbb, 0x80, 0x4d, 0x3f, 0x37, 0x9b, 0x52, 0xe2, 0x2d, 0x68, 0xca, 0x2b, - 0xd0, 0x2c, 0x3b, 0x36, 0xd5, 0x7c, 0xf6, 0x1b, 0x84, 0xf1, 0xe4, 0x16, 0xe1, 0xc2, 0x4a, 0x84, - 0xf1, 0xe4, 0x26, 0xe1, 0x6f, 0x21, 0x7a, 0xd7, 0x10, 0xcb, 0xe8, 0xe1, 0x21, 0xa6, 0x26, 0x51, - 0x90, 0x10, 0xac, 0x7e, 0x84, 0xa0, 0x46, 0xb9, 0x2e, 0xc7, 0x44, 0x87, 0x01, 0x0f, 0xfa, 0x02, - 0x94, 0x31, 0xed, 0xb9, 0xd4, 0xb2, 0x69, 0xdf, 0x18, 0x11, 0xcf, 0x76, 0x2d, 0x83, 0x11, 0xd3, - 0xa5, 0x16, 0x53, 0x8a, 0xdb, 0xd2, 0x6e, 0x5a, 0x2f, 0xc7, 0xf8, 0xa9, 0x80, 0xdb, 0x01, 0x8a, - 0xca, 0xb0, 0x36, 0xc0, 0x43, 0x4e, 0x2c, 0xa5, 0xb4, 0x2d, 0xed, 0x66, 0xf4, 0x70, 0xb5, 0xf3, - 0x87, 0x04, 0x72, 0x23, 0x7e, 0x37, 0xea, 0xc4, 0x74, 0x3d, 0x0b, 0xe5, 0x20, 0x19, 0xce, 0x82, - 0xb4, 0x9e, 0xb4, 0x2d, 0xd4, 0x86, 0x6c, 0xf8, 0x62, 0xc7, 0x8e, 0x3b, 0xa6, 0x3c, 0x98, 0x00, - 0x1f, 0x9d, 0xcf, 0x46, 0x40, 0x52, 0x13, 0x1c, 0xe8, 0x39, 0xac, 0x31, 0x8e, 0xf9, 0x98, 0x89, - 0xe9, 0x90, 0x3b, 0xf8, 0x7f, 0x75, 0x6e, 0xac, 0x55, 0xe7, 0xf7, 0xd5, 0x16, 0xee, 0x7a, 0x18, - 0x86, 0x1e, 0xc0, 0x3a, 0x9f, 0x18, 0x03, 0xcc, 0x06, 0xe1, 0xb4, 0x58, 0xe3, 0x93, 0x97, 0x98, - 0x0d, 0x76, 0x7e, 0x4f, 0x41, 0xbe, 0x1b, 0x95, 0xe1, 0x96, 0x94, 0x9e, 0xc5, 0xea, 0x49, 0xa1, - 0xfe, 0x78, 0x41, 0x7d, 0x8e, 0x61, 0x4e, 0xfc, 0x1b, 0xc8, 0x33, 0x1e, 0xce, 0xb9, 0xb0, 0x28, - 0xa9, 0x7f, 0x55, 0x94, 0x2c, 0xe3, 0x62, 0x20, 0x86, 0x55, 0x59, 0x28, 0x75, 0x7a, 0x05, 0xa5, - 0xd6, 0xe0, 0x7f, 0xd3, 0x63, 0x63, 0xba, 0xce, 0x68, 0x48, 0xc4, 0x65, 0xe0, 0xb6, 0x43, 0xe2, - 0xf3, 0x73, 0x47, 0xd4, 0xa6, 0x12, 0x3b, 0xd6, 0x63, 0xbf, 0x8e, 0xed, 0x90, 0xe8, 0x1c, 0x7d, - 0x06, 0xa5, 0x31, 0x9d, 0x19, 0xc0, 0x51, 0x07, 0xc4, 0xec, 0xd4, 0xd1, 0x2c, 0xd6, 0x11, 0xdd, - 0x40, 0xcf, 0xe0, 0x61, 0xc0, 0x49, 0xac, 0xb0, 0x5e, 0xec, 0x82, 0x90, 0x51, 0x1c, 0x29, 0x66, - 0xa6, 0xae, 0x44, 0x3e, 0xa2, 0x18, 0x6d, 0xdf, 0x23, 0x88, 0xdf, 0xf9, 0x29, 0x09, 0xf2, 0xcc, - 0x1d, 0x0b, 0xda, 0x59, 0x85, 0xe2, 0x34, 0x23, 0x4f, 0xd8, 0x8c, 0xb8, 0xbf, 0x85, 0xf1, 0xf5, - 0xd6, 0x69, 0x16, 0xda, 0x82, 0x8c, 0xff, 0x12, 0x20, 0x0e, 0xf1, 0xc2, 0xcf, 0x97, 0x78, 0xfd, - 0x9f, 0x6a, 0xe5, 0xce, 0x6f, 0x12, 0xdc, 0x6b, 0x0f, 0x31, 0x1b, 0xdc, 0x72, 0xae, 0x11, 0xa4, - 0xfd, 0xae, 0x8a, 0x24, 0xd3, 0xba, 0x78, 0x5e, 0xdc, 0x48, 0x6a, 0x05, 0x67, 0xea, 0x13, 0x28, - 0x9c, 0xe3, 0xa1, 0x6d, 0xcd, 0x7e, 0x33, 0x84, 0xf7, 0x50, 0x8e, 0x81, 0x70, 0x82, 0x3f, 0xf9, - 0x1e, 0xca, 0x37, 0x5f, 0x66, 0xa4, 0x40, 0xa9, 0xa3, 0xd7, 0x5a, 0xed, 0x17, 0xaa, 0x6e, 0x68, - 0x2d, 0xe3, 0x54, 0x3f, 0x39, 0xd2, 0xd5, 0x76, 0x5b, 0x4e, 0xa0, 0x22, 0xe4, 0x63, 0xe4, 0x45, - 0x4d, 0x6b, 0xaa, 0x0d, 0x59, 0x42, 0x25, 0x90, 0x1b, 0x6a, 0x53, 0x3d, 0xaa, 0x75, 0xb4, 0x93, - 0x96, 0xf1, 0x75, 0x57, 0xed, 0xaa, 0x72, 0x12, 0x3d, 0x80, 0xe2, 0x8c, 0xb5, 0x7e, 0x72, 0x7c, - 0xda, 0x54, 0x3b, 0xaa, 0x9c, 0xda, 0x4a, 0xff, 0xf8, 0x6b, 0x25, 0xf1, 0xe4, 0x17, 0x09, 0xee, - 0xdf, 0x78, 0x9b, 0xd1, 0x43, 0x50, 0x6a, 0xf5, 0x7a, 0xf7, 0xb8, 0xdb, 0xac, 0x75, 0xb4, 0xd6, - 0x91, 0xa1, 0xab, 0x0d, 0xf5, 0xf8, 0xd4, 0x67, 0x09, 0x77, 0xd0, 0x6d, 0x1d, 0x9e, 0xb4, 0x1a, - 0x3e, 0x14, 0x68, 0x49, 0x68, 0x13, 0xee, 0x4f, 0x8d, 0xb3, 0x3b, 0x4e, 0xa2, 0x0d, 0xc8, 0x04, - 0x90, 0xda, 0x90, 0x53, 0x28, 0x0b, 0x77, 0xeb, 0xcd, 0x9a, 0x76, 0x5c, 0x3b, 0x6c, 0xaa, 0x72, - 0x1a, 0xdd, 0x83, 0x75, 0xb1, 0x54, 0x1b, 0xf2, 0x9d, 0x60, 0x5f, 0x87, 0xcd, 0xb7, 0x97, 0x15, - 0xe9, 0xdd, 0x65, 0x45, 0xfa, 0xfb, 0xb2, 0x22, 0xfd, 0x7c, 0x55, 0x49, 0xbc, 0xbb, 0xaa, 0x24, - 0xfe, 0xbc, 0xaa, 0x24, 0x5e, 0x1d, 0xcc, 0xb4, 0x24, 0xf8, 0xf8, 0xd9, 0x6b, 0xe2, 0x1e, 0xdb, - 0x0f, 0xff, 0x18, 0x9c, 0x1f, 0x7c, 0xbe, 0x3f, 0x99, 0xfe, 0x3d, 0x10, 0x2d, 0xea, 0xad, 0x89, - 0x4f, 0xfb, 0xa7, 0xff, 0x04, 0x00, 0x00, 0xff, 0xff, 0x01, 0x06, 0xc8, 0xce, 0x3e, 0x0c, 0x00, - 0x00, + // 1024 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xd4, 0x56, 0xcf, 0x6e, 0x1b, 0x45, + 0x18, 0xf7, 0xda, 0xae, 0xe3, 0x7e, 0x89, 0x93, 0xcd, 0xd8, 0x4d, 0x36, 0xa1, 0x72, 0x43, 0x0e, + 0x25, 0x2a, 0xc4, 0x41, 0x29, 0x07, 0x2e, 0xb4, 0x72, 0xec, 0x6d, 0x6a, 0xe4, 0x38, 0x61, 0x6d, + 0x73, 0xe8, 0x65, 0x35, 0xf6, 0x4c, 0xed, 0x55, 0xbc, 0x33, 0xd6, 0xce, 0x38, 0x0d, 0x12, 0x0f, + 0x80, 0xc4, 0x85, 0x0b, 0x4f, 0xc0, 0x23, 0xc0, 0x43, 0x54, 0xe2, 0x52, 0x38, 0x21, 0x0e, 0x15, + 0x4a, 0x1e, 0x83, 0x0b, 0xda, 0xd9, 0xd9, 0xb5, 0xf3, 0xa7, 0xb2, 0x40, 0xbd, 0x70, 0xf2, 0xce, + 0xf7, 0xfb, 0x7e, 0xbf, 0x99, 0xf9, 0xfe, 0x79, 0xa0, 0x2c, 0x64, 0xe0, 0x11, 0xba, 0x27, 0x24, + 0x3e, 0xa5, 0xd2, 0xc3, 0xc9, 0x47, 0x65, 0x1c, 0x70, 0xc9, 0xd1, 0x4a, 0x84, 0x57, 0x62, 0xf3, + 0xe6, 0x46, 0x9f, 0x0b, 0x9f, 0x0b, 0x57, 0xc1, 0x7b, 0xd1, 0x22, 0xf2, 0xdd, 0x2c, 0x0d, 0xf8, + 0x80, 0x47, 0xf6, 0xf0, 0x2b, 0xb2, 0x6e, 0xff, 0x9d, 0x83, 0xfc, 0x73, 0x2e, 0xe4, 0x0b, 0xce, + 0x28, 0xda, 0x80, 0x7c, 0x7f, 0x88, 0x3d, 0xe6, 0x7a, 0xc4, 0x32, 0xb6, 0x8c, 0x9d, 0xbb, 0xce, + 0x82, 0x5a, 0x37, 0x08, 0xfa, 0x04, 0x10, 0xc3, 0xd2, 0x3b, 0xa3, 0xae, 0xe4, 0xa7, 0x94, 0xb9, + 0x84, 0x32, 0xee, 0x5b, 0x69, 0xe5, 0x64, 0x46, 0x48, 0x27, 0x04, 0xea, 0xa1, 0x1d, 0x3d, 0x86, + 0xb5, 0x2b, 0xde, 0x5e, 0xaf, 0xaf, 0x19, 0x19, 0xc5, 0x28, 0xce, 0x30, 0x1a, 0xbd, 0x7e, 0x44, + 0xaa, 0x40, 0x51, 0x06, 0x98, 0x89, 0x97, 0x34, 0x70, 0xfb, 0x43, 0xcc, 0x18, 0x1d, 0x85, 0x07, + 0xc9, 0x2a, 0xc6, 0x6a, 0x0c, 0xd5, 0x22, 0xa4, 0x41, 0xd0, 0x21, 0x20, 0x42, 0x47, 0x74, 0x80, + 0xa5, 0xc7, 0x99, 0x8b, 0x09, 0x09, 0xa8, 0x10, 0xd6, 0x9d, 0xd0, 0xfd, 0xc0, 0xfa, 0xfd, 0x97, + 0xdd, 0x92, 0xbe, 0x7e, 0x35, 0x42, 0xda, 0x32, 0xf0, 0xd8, 0xc0, 0x59, 0x9d, 0x72, 0x34, 0x80, + 0x9e, 0xc2, 0x72, 0x40, 0x5f, 0xe1, 0x80, 0x24, 0x22, 0xb9, 0x39, 0x22, 0x85, 0xc8, 0x3f, 0x16, + 0xa8, 0xc2, 0x0a, 0xa1, 0x63, 0x2e, 0x3c, 0x99, 0x28, 0x2c, 0xcc, 0x51, 0x58, 0xd6, 0x84, 0x58, + 0xe2, 0x10, 0x50, 0x40, 0x09, 0xf5, 0xc7, 0x57, 0x2e, 0x93, 0x9f, 0x77, 0x99, 0x29, 0x27, 0x16, + 0xfa, 0x02, 0x0a, 0xfd, 0x11, 0xf6, 0xfc, 0x44, 0xe3, 0xee, 0x1c, 0x8d, 0x25, 0xe5, 0x1e, 0xd3, + 0xbb, 0xb0, 0xc9, 0xc7, 0x34, 0xc0, 0x92, 0x07, 0xb1, 0x82, 0xcb, 0x99, 0x1b, 0xd5, 0x99, 0x05, + 0x73, 0xb4, 0xd6, 0x63, 0xae, 0x36, 0x1f, 0xb3, 0xb6, 0x22, 0xa2, 0x23, 0x58, 0x13, 0xf8, 0x25, + 0xbd, 0x45, 0x72, 0x71, 0x8e, 0x64, 0x31, 0xe4, 0x5d, 0x97, 0x63, 0xf0, 0x41, 0x40, 0x7d, 0xec, + 0x31, 0x8f, 0x0d, 0x5c, 0x9d, 0x50, 0x4a, 0xdc, 0x1e, 0x1e, 0x61, 0xd6, 0xa7, 0x16, 0x52, 0x9a, + 0x95, 0xd7, 0x6f, 0x1f, 0xa4, 0xfe, 0x7c, 0xfb, 0xe0, 0xe1, 0xc0, 0x93, 0xc3, 0x49, 0xaf, 0xd2, + 0xe7, 0xbe, 0xee, 0x08, 0xfd, 0xb3, 0x2b, 0xc8, 0xe9, 0x9e, 0xfc, 0x66, 0x4c, 0x45, 0xa5, 0xc1, + 0xa4, 0xb3, 0x91, 0x48, 0xd6, 0x63, 0xc5, 0x83, 0x48, 0x10, 0x7d, 0x0e, 0xd6, 0x84, 0xf5, 0x38, + 0x23, 0xe1, 0x7e, 0x63, 0x1a, 0x78, 0x9c, 0xb8, 0x82, 0xf6, 0x39, 0x23, 0xc2, 0x2a, 0x6e, 0x19, + 0x3b, 0x59, 0x67, 0x2d, 0xc1, 0x4f, 0x14, 0xdc, 0x8e, 0x50, 0xb4, 0x06, 0xb9, 0x21, 0x1e, 0x49, + 0x4a, 0xac, 0xd2, 0x96, 0xb1, 0x93, 0x77, 0xf4, 0xea, 0xcb, 0x6c, 0xbe, 0x60, 0x2e, 0x6f, 0xff, + 0x66, 0x80, 0x59, 0x4f, 0xea, 0xd1, 0xa1, 0x7d, 0x1e, 0x10, 0xb4, 0x0c, 0x69, 0xdd, 0x7f, 0x59, + 0x27, 0xed, 0x11, 0xd4, 0x86, 0x82, 0x6e, 0x26, 0xec, 0xf3, 0x09, 0x93, 0x51, 0xd7, 0xfd, 0xeb, + 0xeb, 0x2d, 0x45, 0x22, 0x55, 0xa5, 0x81, 0x9e, 0x42, 0x4e, 0x48, 0x2c, 0x27, 0x42, 0x75, 0xe4, + 0xf2, 0xfe, 0x47, 0x95, 0x6b, 0xa3, 0xa4, 0x72, 0xfd, 0x5c, 0x6d, 0xe5, 0xee, 0x68, 0x1a, 0x5a, + 0x87, 0x05, 0x79, 0xee, 0x0e, 0xb1, 0x18, 0xea, 0x0e, 0xcd, 0xc9, 0xf3, 0xe7, 0x58, 0x0c, 0xb7, + 0x7f, 0xcd, 0xc0, 0x4a, 0x37, 0x0e, 0xc6, 0x3b, 0xae, 0xf4, 0x24, 0xd9, 0x3d, 0xad, 0x76, 0x7f, + 0x78, 0x63, 0xf7, 0x6b, 0x0a, 0xd7, 0x36, 0xff, 0x1a, 0x56, 0x84, 0xd4, 0xb3, 0x45, 0x07, 0x25, + 0xf3, 0x9f, 0x82, 0x52, 0x10, 0x52, 0x0d, 0x21, 0x1d, 0x95, 0x1b, 0xa1, 0xce, 0xbe, 0x87, 0x50, + 0x37, 0xe0, 0xc3, 0x69, 0xf1, 0xf4, 0xb9, 0x3f, 0x1e, 0x51, 0xd5, 0xe4, 0xd2, 0xf3, 0x69, 0x52, + 0x45, 0x77, 0x54, 0x6c, 0xca, 0x89, 0x63, 0x2d, 0xf1, 0xeb, 0x78, 0x3e, 0x8d, 0xab, 0xe9, 0x53, + 0x28, 0x4d, 0xd8, 0xcc, 0xd0, 0x8b, 0x33, 0xa0, 0xe6, 0x95, 0x83, 0x66, 0xb1, 0x8e, 0xca, 0x06, + 0x7a, 0x02, 0xf7, 0x23, 0x4d, 0x4a, 0x74, 0xbc, 0xc4, 0x2b, 0x4a, 0xc7, 0x09, 0x53, 0xcd, 0x29, + 0xc7, 0x8a, 0x7d, 0x54, 0x30, 0xda, 0xa1, 0x47, 0xc4, 0xdf, 0xfe, 0x3e, 0x0d, 0xa6, 0x93, 0x0c, + 0x19, 0x9d, 0xce, 0x0a, 0x14, 0xa7, 0x37, 0x0a, 0x94, 0xcd, 0x4d, 0xf2, 0xbb, 0x3a, 0xb9, 0x9a, + 0xba, 0x06, 0x41, 0x9b, 0x90, 0x0f, 0x07, 0x15, 0xf5, 0x69, 0xa0, 0xff, 0x32, 0x92, 0xf5, 0xff, + 0x2a, 0x95, 0xdb, 0x3f, 0x1b, 0xb0, 0xd8, 0x1e, 0x61, 0x31, 0x7c, 0x47, 0x5d, 0x23, 0xc8, 0x86, + 0x59, 0x55, 0x97, 0xcc, 0x3a, 0xea, 0xfb, 0xe6, 0x41, 0x32, 0xef, 0xa1, 0xa6, 0x3e, 0x86, 0xd5, + 0x33, 0x3c, 0xf2, 0xc8, 0xec, 0x9c, 0xd6, 0x7d, 0x68, 0x26, 0x80, 0x9e, 0x9a, 0x8f, 0xbe, 0x85, + 0xb5, 0xdb, 0x9b, 0x19, 0x59, 0x50, 0xea, 0x38, 0xd5, 0x56, 0xfb, 0x99, 0xed, 0xb8, 0x8d, 0x96, + 0x7b, 0xe2, 0x1c, 0x1f, 0x3a, 0x76, 0xbb, 0x6d, 0xa6, 0x50, 0x11, 0x56, 0x12, 0xe4, 0x59, 0xb5, + 0xd1, 0xb4, 0xeb, 0xa6, 0x81, 0x4a, 0x60, 0xd6, 0xed, 0xa6, 0x7d, 0x58, 0xed, 0x34, 0x8e, 0x5b, + 0xee, 0x57, 0x5d, 0xbb, 0x6b, 0x9b, 0x69, 0xb4, 0x0e, 0xc5, 0x19, 0x6b, 0xed, 0xf8, 0xe8, 0xa4, + 0x69, 0x77, 0x6c, 0x33, 0xb3, 0x99, 0xfd, 0xee, 0xa7, 0x72, 0xea, 0xd1, 0x8f, 0x06, 0xdc, 0xbb, + 0xb5, 0x9b, 0xd1, 0x7d, 0xb0, 0xaa, 0xb5, 0x5a, 0xf7, 0xa8, 0xdb, 0xac, 0x76, 0x1a, 0xad, 0x43, + 0xd7, 0xb1, 0xeb, 0xf6, 0xd1, 0x49, 0xa8, 0xa2, 0x4f, 0xd0, 0x6d, 0x1d, 0x1c, 0xb7, 0xea, 0x21, + 0x14, 0xed, 0x65, 0xa0, 0x0d, 0xb8, 0x37, 0x35, 0xce, 0x9e, 0x38, 0x8d, 0x96, 0x20, 0x1f, 0x41, + 0x76, 0xdd, 0xcc, 0xa0, 0x02, 0xdc, 0xad, 0x35, 0xab, 0x8d, 0xa3, 0xea, 0x41, 0xd3, 0x36, 0xb3, + 0x68, 0x11, 0x16, 0xd4, 0xd2, 0xae, 0x9b, 0x77, 0xa2, 0x73, 0x1d, 0x34, 0x5f, 0x5f, 0x94, 0x8d, + 0x37, 0x17, 0x65, 0xe3, 0xaf, 0x8b, 0xb2, 0xf1, 0xc3, 0x65, 0x39, 0xf5, 0xe6, 0xb2, 0x9c, 0xfa, + 0xe3, 0xb2, 0x9c, 0x7a, 0xb1, 0x3f, 0x93, 0x92, 0xe8, 0x0f, 0x67, 0xb7, 0x89, 0x7b, 0x62, 0x4f, + 0x3f, 0xc6, 0xce, 0xf6, 0x3f, 0xdb, 0x3b, 0x9f, 0x3e, 0xc9, 0x54, 0x8a, 0x7a, 0x39, 0xf5, 0x9c, + 0x7a, 0xfc, 0x4f, 0x00, 0x00, 0x00, 0xff, 0xff, 0xf9, 0x86, 0xdb, 0x83, 0xb2, 0x09, 0x00, 0x00, } func (m *HostZone) Marshal() (dAtA []byte, err error) { @@ -695,9 +676,9 @@ func (m *HostZone) MarshalToSizedBuffer(dAtA []byte) (int, error) { dAtA[i] = 0x98 } { - size := m.DelegatedBalance.Size() + size := m.RemainingDelegatedBalance.Size() i -= size - if _, err := m.DelegatedBalance.MarshalTo(dAtA[i:]); err != nil { + if _, err := m.RemainingDelegatedBalance.MarshalTo(dAtA[i:]); err != nil { return 0, err } i = encodeVarintStaketia(dAtA, i, uint64(size)) @@ -706,70 +687,6 @@ func (m *HostZone) MarshalToSizedBuffer(dAtA []byte) (int, error) { dAtA[i] = 0x1 i-- dAtA[i] = 0x92 - { - size := m.MaxInnerRedemptionRate.Size() - i -= size - if _, err := m.MaxInnerRedemptionRate.MarshalTo(dAtA[i:]); err != nil { - return 0, err - } - i = encodeVarintStaketia(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x1 - i-- - dAtA[i] = 0x8a - { - size := m.MinInnerRedemptionRate.Size() - i -= size - if _, err := m.MinInnerRedemptionRate.MarshalTo(dAtA[i:]); err != nil { - return 0, err - } - i = encodeVarintStaketia(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x1 - i-- - dAtA[i] = 0x82 - { - size := m.MaxRedemptionRate.Size() - i -= size - if _, err := m.MaxRedemptionRate.MarshalTo(dAtA[i:]); err != nil { - return 0, err - } - i = encodeVarintStaketia(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x7a - { - size := m.MinRedemptionRate.Size() - i -= size - if _, err := m.MinRedemptionRate.MarshalTo(dAtA[i:]); err != nil { - return 0, err - } - i = encodeVarintStaketia(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x72 - { - size := m.RedemptionRate.Size() - i -= size - if _, err := m.RedemptionRate.MarshalTo(dAtA[i:]); err != nil { - return 0, err - } - i = encodeVarintStaketia(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x6a - { - size := m.LastRedemptionRate.Size() - i -= size - if _, err := m.LastRedemptionRate.MarshalTo(dAtA[i:]); err != nil { - return 0, err - } - i = encodeVarintStaketia(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x62 if len(m.SafeAddressOnStride) > 0 { i -= len(m.SafeAddressOnStride) copy(dAtA[i:], m.SafeAddressOnStride) @@ -1138,19 +1055,7 @@ func (m *HostZone) Size() (n int) { if l > 0 { n += 1 + l + sovStaketia(uint64(l)) } - l = m.LastRedemptionRate.Size() - n += 1 + l + sovStaketia(uint64(l)) - l = m.RedemptionRate.Size() - n += 1 + l + sovStaketia(uint64(l)) - l = m.MinRedemptionRate.Size() - n += 1 + l + sovStaketia(uint64(l)) - l = m.MaxRedemptionRate.Size() - n += 1 + l + sovStaketia(uint64(l)) - l = m.MinInnerRedemptionRate.Size() - n += 2 + l + sovStaketia(uint64(l)) - l = m.MaxInnerRedemptionRate.Size() - n += 2 + l + sovStaketia(uint64(l)) - l = m.DelegatedBalance.Size() + l = m.RemainingDelegatedBalance.Size() n += 2 + l + sovStaketia(uint64(l)) if m.UnbondingPeriodSeconds != 0 { n += 2 + sovStaketia(uint64(m.UnbondingPeriodSeconds)) @@ -1640,213 +1545,9 @@ func (m *HostZone) Unmarshal(dAtA []byte) error { } m.SafeAddressOnStride = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex - case 12: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field LastRedemptionRate", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowStaketia - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLengthStaketia - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthStaketia - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if err := m.LastRedemptionRate.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 13: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field RedemptionRate", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowStaketia - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLengthStaketia - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthStaketia - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if err := m.RedemptionRate.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 14: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field MinRedemptionRate", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowStaketia - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLengthStaketia - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthStaketia - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if err := m.MinRedemptionRate.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 15: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field MaxRedemptionRate", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowStaketia - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLengthStaketia - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthStaketia - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if err := m.MaxRedemptionRate.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 16: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field MinInnerRedemptionRate", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowStaketia - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLengthStaketia - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthStaketia - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if err := m.MinInnerRedemptionRate.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 17: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field MaxInnerRedemptionRate", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowStaketia - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLengthStaketia - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthStaketia - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if err := m.MaxInnerRedemptionRate.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex case 18: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field DelegatedBalance", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field RemainingDelegatedBalance", wireType) } var stringLen uint64 for shift := uint(0); ; shift += 7 { @@ -1874,7 +1575,7 @@ func (m *HostZone) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - if err := m.DelegatedBalance.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + if err := m.RemainingDelegatedBalance.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } iNdEx = postIndex diff --git a/x/staketia/types/tx.pb.go b/x/staketia/types/tx.pb.go index fdad18951e..94bc429da5 100644 --- a/x/staketia/types/tx.pb.go +++ b/x/staketia/types/tx.pb.go @@ -61,7 +61,10 @@ func (OverwritableRecordType) EnumDescriptor() ([]byte, []int) { return fileDescriptor_98ceebce67c1ff4c, []int{0} } +// Deprecated: Liquid stakes should be handled in stakeibc // LiquidStake +// +// Deprecated: Do not use. type MsgLiquidStake struct { Staker string `protobuf:"bytes,1,opt,name=staker,proto3" json:"staker,omitempty"` NativeAmount github_com_cosmos_cosmos_sdk_types.Int `protobuf:"bytes,2,opt,name=native_amount,json=nativeAmount,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Int" json:"native_amount"` @@ -107,6 +110,7 @@ func (m *MsgLiquidStake) GetStaker() string { return "" } +// Deprecated: Do not use. type MsgLiquidStakeResponse struct { StToken types.Coin `protobuf:"bytes,1,opt,name=st_token,json=stToken,proto3,castrepeated=github.com/cosmos/cosmos-sdk/types.Coins" json:"st_token"` } @@ -155,6 +159,9 @@ func (m *MsgLiquidStakeResponse) GetStToken() types.Coin { type MsgRedeemStake struct { Redeemer string `protobuf:"bytes,1,opt,name=redeemer,proto3" json:"redeemer,omitempty"` StTokenAmount github_com_cosmos_cosmos_sdk_types.Int `protobuf:"bytes,2,opt,name=st_token_amount,json=stTokenAmount,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Int" json:"st_token_amount"` + // The receiver field is a celestia address + // It is only used in the case where the redemption spills over to stakeibc + Receiver string `protobuf:"bytes,3,opt,name=receiver,proto3" json:"receiver,omitempty"` } func (m *MsgRedeemStake) Reset() { *m = MsgRedeemStake{} } @@ -197,6 +204,13 @@ func (m *MsgRedeemStake) GetRedeemer() string { return "" } +func (m *MsgRedeemStake) GetReceiver() string { + if m != nil { + return m.Receiver + } + return "" +} + type MsgRedeemStakeResponse struct { NativeToken types.Coin `protobuf:"bytes,1,opt,name=native_token,json=nativeToken,proto3,castrepeated=github.com/cosmos/cosmos-sdk/types.Coins" json:"native_token"` } @@ -1260,92 +1274,93 @@ func init() { func init() { proto.RegisterFile("stride/staketia/tx.proto", fileDescriptor_98ceebce67c1ff4c) } var fileDescriptor_98ceebce67c1ff4c = []byte{ - // 1356 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x58, 0xcf, 0x6f, 0x1b, 0xc5, - 0x17, 0xf7, 0xa6, 0x55, 0x7f, 0x8c, 0xbf, 0x6d, 0x9d, 0xfd, 0xb6, 0xae, 0xbd, 0xa5, 0x76, 0xba, - 0x6d, 0xd3, 0xd6, 0x6d, 0x76, 0x89, 0xdb, 0x82, 0x64, 0xb8, 0xc4, 0xb5, 0xd5, 0x46, 0xc4, 0x71, - 0xe5, 0x24, 0x54, 0x94, 0xc3, 0xb2, 0xf6, 0x4e, 0xd6, 0x4b, 0xe3, 0x1d, 0x77, 0x67, 0xec, 0xb8, - 0x42, 0x42, 0xc0, 0xa9, 0xe2, 0x84, 0xc4, 0x89, 0x03, 0x27, 0x24, 0x24, 0xb8, 0xd0, 0x03, 0x37, - 0x2e, 0x1c, 0x7b, 0xac, 0x38, 0x21, 0x0e, 0x05, 0x25, 0x87, 0x8a, 0x7f, 0x00, 0xae, 0x68, 0x7f, - 0x76, 0x76, 0x77, 0xd6, 0x76, 0x0a, 0xb9, 0xc4, 0xde, 0x79, 0x9f, 0x79, 0xef, 0xf3, 0x3e, 0x6f, - 0xf6, 0xcd, 0x8b, 0x41, 0x0e, 0x13, 0xcb, 0xd0, 0xa0, 0x8c, 0x89, 0xfa, 0x00, 0x12, 0x43, 0x95, - 0xc9, 0x48, 0xea, 0x5b, 0x88, 0x20, 0xfe, 0x84, 0x6b, 0x91, 0x7c, 0x8b, 0x70, 0xba, 0x83, 0x70, - 0x0f, 0x61, 0xb9, 0x87, 0x75, 0x79, 0xb8, 0x68, 0x7f, 0xb8, 0x48, 0x61, 0x56, 0xed, 0x19, 0x26, - 0x92, 0x9d, 0xbf, 0xde, 0xd2, 0x49, 0x1d, 0xe9, 0xc8, 0xf9, 0x2a, 0xdb, 0xdf, 0xbc, 0xd5, 0x82, - 0xe7, 0xa1, 0xad, 0x62, 0x28, 0x0f, 0x17, 0xdb, 0x90, 0xa8, 0x8b, 0x72, 0x07, 0x19, 0xa6, 0x67, - 0xcf, 0xbb, 0x76, 0xc5, 0xdd, 0xe8, 0x3e, 0xf8, 0x5b, 0xa3, 0x3c, 0xfd, 0x2f, 0xae, 0x5d, 0xfc, - 0x96, 0x03, 0xc7, 0x1b, 0x58, 0x5f, 0x31, 0x1e, 0x0e, 0x0c, 0x6d, 0xcd, 0xb6, 0xf1, 0x59, 0x70, - 0xc8, 0x01, 0x59, 0x39, 0x6e, 0x8e, 0xbb, 0x7c, 0xb4, 0xe5, 0x3d, 0xf1, 0x6b, 0xe0, 0x98, 0xa9, - 0x12, 0x63, 0x08, 0x15, 0xb5, 0x87, 0x06, 0x26, 0xc9, 0xcd, 0xd8, 0xe6, 0xaa, 0xf4, 0xf4, 0x79, - 0x31, 0xf5, 0xdb, 0xf3, 0xe2, 0xbc, 0x6e, 0x90, 0xee, 0xa0, 0x2d, 0x75, 0x50, 0xcf, 0xa3, 0xe0, - 0x7d, 0x2c, 0x60, 0xed, 0x81, 0x4c, 0x1e, 0xf5, 0x21, 0x96, 0x96, 0x4d, 0xd2, 0xfa, 0x9f, 0xeb, - 0x64, 0xc9, 0xf1, 0x51, 0xb9, 0xf4, 0xd9, 0x8b, 0x27, 0x25, 0x2f, 0xc2, 0xe7, 0x2f, 0x9e, 0x94, - 0x4e, 0x07, 0x44, 0xc3, 0xac, 0xc4, 0x4f, 0x38, 0x90, 0x0d, 0x2f, 0xb5, 0x20, 0xee, 0x23, 0x13, - 0x43, 0x7e, 0x13, 0x1c, 0xc1, 0x44, 0x21, 0xe8, 0x01, 0x34, 0x1d, 0xca, 0xe9, 0x72, 0x5e, 0xf2, - 0x44, 0xb0, 0x15, 0x93, 0x3c, 0xc5, 0xa4, 0x5b, 0xc8, 0x30, 0xab, 0xaf, 0xdb, 0x74, 0xbf, 0xff, - 0xbd, 0x78, 0x79, 0x0a, 0xba, 0xf6, 0x06, 0xdc, 0x3a, 0x8c, 0xc9, 0xba, 0xed, 0x5b, 0xfc, 0xc1, - 0xd5, 0xaa, 0x05, 0x35, 0x08, 0x7b, 0xae, 0x56, 0x02, 0x38, 0x62, 0x39, 0x8f, 0x81, 0x5a, 0xc1, - 0x33, 0xff, 0x2e, 0x38, 0xe1, 0xd3, 0xfa, 0x77, 0x8a, 0x1d, 0xf3, 0x08, 0x78, 0x92, 0x5d, 0xb1, - 0x25, 0x0b, 0xc2, 0xc4, 0x44, 0xa3, 0xe8, 0x89, 0x8f, 0x5d, 0xd1, 0xa8, 0xa5, 0x40, 0x34, 0x13, - 0x78, 0x85, 0xd8, 0x3f, 0xe1, 0xd2, 0x6e, 0x00, 0x57, 0xbc, 0xaf, 0x38, 0x70, 0xb2, 0x81, 0xf5, - 0x5b, 0xc8, 0xdc, 0x34, 0xac, 0x5e, 0x0d, 0x6e, 0x41, 0x5d, 0x25, 0x06, 0x32, 0x6d, 0x09, 0x51, - 0x1f, 0x5a, 0x2a, 0x41, 0x81, 0x84, 0xfe, 0x33, 0x7f, 0x06, 0x1c, 0xb5, 0x60, 0x07, 0x59, 0x9a, - 0x62, 0x68, 0x8e, 0x78, 0x07, 0x6d, 0x7d, 0xed, 0x85, 0x65, 0x8d, 0x3f, 0x0d, 0x0e, 0x93, 0x91, - 0xd2, 0x55, 0x71, 0x37, 0x77, 0xc0, 0x3d, 0xa8, 0x64, 0x74, 0x47, 0xc5, 0xdd, 0x8a, 0xec, 0x08, - 0xe4, 0x3b, 0xb1, 0x05, 0x3a, 0x4b, 0x0b, 0x14, 0xa3, 0x20, 0x16, 0xc0, 0x6b, 0xac, 0x75, 0x5f, - 0x2b, 0xf1, 0x6b, 0x57, 0x46, 0x0f, 0xb0, 0x61, 0x6a, 0xfb, 0xc9, 0x7e, 0x31, 0xc6, 0xbe, 0xc8, - 0x60, 0x4f, 0x93, 0x10, 0xe7, 0x40, 0x81, 0x6d, 0x09, 0x32, 0xf8, 0x8e, 0xa3, 0x53, 0xdc, 0x30, - 0xdb, 0xc8, 0xd4, 0xa0, 0xe6, 0x54, 0x66, 0x6d, 0x1b, 0xc2, 0xfe, 0x3e, 0xe4, 0xf1, 0x66, 0x2c, - 0x8f, 0x8b, 0xcc, 0x3c, 0xa2, 0x54, 0xc4, 0x79, 0x70, 0x61, 0x9c, 0x3d, 0xc8, 0xe9, 0x6f, 0x0e, - 0xe4, 0x1b, 0x58, 0x5f, 0xd2, 0x3e, 0x1c, 0x60, 0xe2, 0x55, 0x0d, 0x6a, 0x55, 0x75, 0x4b, 0x35, - 0x3b, 0x70, 0x6c, 0x42, 0xef, 0x83, 0xd9, 0x97, 0x1a, 0x29, 0x68, 0x73, 0x13, 0xc3, 0x57, 0x7d, - 0x37, 0x33, 0x2f, 0x1d, 0x35, 0x1d, 0x3f, 0xfc, 0x55, 0x30, 0x3b, 0x54, 0xb7, 0x0c, 0xcd, 0x8e, - 0xa4, 0xa8, 0x9a, 0x66, 0x41, 0x8c, 0x3d, 0x69, 0x32, 0x81, 0x61, 0xc9, 0x5d, 0xaf, 0xdc, 0x88, - 0x89, 0x24, 0xd2, 0x22, 0xb1, 0x73, 0x13, 0xcf, 0x83, 0x73, 0x89, 0xc6, 0x40, 0x9e, 0x3f, 0x67, - 0x80, 0xd8, 0xc0, 0xfa, 0x46, 0x5f, 0x53, 0x09, 0x5c, 0x36, 0x4d, 0x68, 0xd9, 0x6d, 0xa0, 0xd7, - 0x77, 0xce, 0x85, 0x4a, 0x60, 0x15, 0x0d, 0x4c, 0x0d, 0xf3, 0x39, 0x70, 0xb8, 0x63, 0x41, 0x4a, - 0x26, 0xff, 0x91, 0xdf, 0x06, 0xf9, 0x9e, 0x61, 0x2a, 0x86, 0xbd, 0x55, 0xb1, 0x82, 0xbd, 0x8a, - 0xa5, 0x12, 0xe8, 0xa9, 0xf5, 0xf6, 0x1e, 0xd4, 0xaa, 0xc1, 0xce, 0x2f, 0x3f, 0x2e, 0x00, 0xaf, - 0xbf, 0xd4, 0x60, 0xa7, 0x95, 0xed, 0x19, 0x26, 0x83, 0x98, 0x13, 0x58, 0x1d, 0x25, 0x04, 0x3e, - 0xf0, 0x9f, 0x04, 0x56, 0x47, 0x8c, 0xc0, 0xee, 0x91, 0xf5, 0xf3, 0xb7, 0x8b, 0x31, 0x4f, 0x17, - 0xc3, 0x55, 0x92, 0x25, 0xa2, 0x78, 0x0d, 0x94, 0x26, 0x4b, 0x1d, 0x54, 0xe6, 0x3e, 0x98, 0x75, - 0x9a, 0x32, 0x1e, 0xf4, 0xe0, 0x1d, 0x84, 0xc9, 0x7d, 0x64, 0xc2, 0xe4, 0x3a, 0x54, 0xae, 0x46, - 0x59, 0x09, 0xe1, 0x76, 0x4f, 0xbb, 0x11, 0xcf, 0x38, 0xef, 0x44, 0x78, 0x31, 0x08, 0xdc, 0x05, - 0x39, 0xc7, 0xb8, 0x69, 0x41, 0xdc, 0x8d, 0x88, 0x9e, 0x1c, 0xbf, 0x1c, 0x8d, 0x7f, 0x2e, 0x1c, - 0x9f, 0xe1, 0x4d, 0x14, 0xc1, 0x5c, 0x92, 0x2d, 0x60, 0xf3, 0xb3, 0xdb, 0x93, 0x9a, 0x43, 0x68, - 0x6d, 0x5b, 0x06, 0x81, 0x74, 0xe3, 0xb5, 0x9b, 0xcb, 0x98, 0xa3, 0xb9, 0x1a, 0x7a, 0x81, 0xdd, - 0x5e, 0xe4, 0x1c, 0xc9, 0x74, 0xf9, 0x9c, 0x14, 0x99, 0xbf, 0xa4, 0xa8, 0x5f, 0xfa, 0x9d, 0x75, - 0x57, 0x2a, 0x6f, 0x44, 0x53, 0x0c, 0xb5, 0xaa, 0x44, 0x86, 0x5e, 0xab, 0x4a, 0xb4, 0x07, 0xa9, - 0xfe, 0xc4, 0x81, 0x33, 0x34, 0xd0, 0xed, 0x6a, 0x86, 0xa9, 0x4f, 0xcc, 0xf4, 0x1d, 0x90, 0x19, - 0xf8, 0xe0, 0x70, 0xa2, 0x73, 0xb1, 0x44, 0x23, 0x5e, 0x5b, 0x27, 0x06, 0xe1, 0x85, 0xca, 0xcd, - 0x68, 0x9a, 0x17, 0x98, 0x69, 0x46, 0xfc, 0x88, 0x17, 0xc1, 0xf9, 0x31, 0xe6, 0xc4, 0x7a, 0x52, - 0x65, 0x9f, 0xa2, 0x9e, 0xf4, 0x7b, 0x3e, 0xbe, 0x9e, 0x51, 0xbf, 0xad, 0x8c, 0x15, 0x59, 0x99, - 0xb6, 0x9e, 0x51, 0x4f, 0xd1, 0x7a, 0xc6, 0x22, 0xf9, 0xa9, 0x7e, 0x04, 0x4e, 0x35, 0xb0, 0xbe, - 0x06, 0x49, 0xd3, 0xeb, 0xdc, 0x5e, 0x3f, 0x77, 0x66, 0x67, 0x43, 0x37, 0xa9, 0xd9, 0xd9, 0x79, - 0x0a, 0xdd, 0x46, 0x33, 0xe1, 0xdb, 0xa8, 0x22, 0xb9, 0x23, 0xb0, 0x03, 0xb4, 0xb9, 0x16, 0x68, - 0xae, 0xf1, 0x18, 0x62, 0x11, 0x9c, 0x65, 0x1a, 0x7c, 0x76, 0xa5, 0x87, 0x20, 0xeb, 0xa7, 0xa0, - 0xb6, 0xb7, 0xa0, 0xcb, 0x7d, 0xfd, 0x51, 0xdf, 0xbe, 0x14, 0xb3, 0xad, 0xfa, 0xad, 0x66, 0xab, - 0xa6, 0xac, 0xbf, 0x77, 0xb7, 0xae, 0xd4, 0xea, 0x2b, 0xf5, 0xdb, 0x4b, 0xeb, 0xcb, 0xcd, 0xd5, - 0x4c, 0x8a, 0xcf, 0x83, 0x53, 0xb4, 0x6d, 0x63, 0xb5, 0xda, 0x5c, 0xad, 0x2d, 0xaf, 0xde, 0xce, - 0x70, 0xd1, 0x6d, 0xad, 0x7a, 0xad, 0xde, 0xb8, 0xeb, 0x6c, 0x9b, 0x11, 0x0e, 0x3e, 0xfe, 0xa6, - 0x90, 0x2a, 0xff, 0x95, 0x06, 0x07, 0x1a, 0x58, 0xe7, 0xef, 0x81, 0x34, 0xfd, 0xaf, 0x44, 0x31, - 0x56, 0xbc, 0xf0, 0x08, 0x2f, 0x5c, 0x9a, 0x00, 0x08, 0xc6, 0xd5, 0x7b, 0x20, 0x4d, 0xcf, 0xdd, - 0x4c, 0xc7, 0x14, 0x80, 0xed, 0x98, 0x35, 0x07, 0x1b, 0x60, 0x36, 0x3e, 0x93, 0x5e, 0x64, 0xed, - 0x8e, 0xc1, 0x84, 0x85, 0xa9, 0x60, 0x41, 0x28, 0x04, 0xfe, 0xcf, 0x1a, 0x21, 0x2f, 0x8d, 0xf1, - 0x42, 0x03, 0x05, 0x79, 0x4a, 0x60, 0x10, 0xf0, 0x53, 0x0e, 0xe4, 0x93, 0x47, 0xbe, 0x85, 0xb1, - 0xee, 0xa2, 0x70, 0xe1, 0xe6, 0x9e, 0xe0, 0x01, 0x87, 0x11, 0xc8, 0x26, 0x4c, 0x68, 0x25, 0x96, - 0x43, 0x36, 0x56, 0x28, 0x4f, 0x8f, 0x0d, 0x22, 0x7f, 0xc9, 0x81, 0xe2, 0xa4, 0xe9, 0xe7, 0x3a, - 0xcb, 0xef, 0x84, 0x4d, 0xc2, 0x5b, 0xaf, 0xb0, 0x29, 0x60, 0xf5, 0x01, 0x38, 0x1e, 0xb9, 0xf9, - 0x45, 0xf6, 0x51, 0xa5, 0x31, 0x42, 0x69, 0x32, 0x26, 0x88, 0x30, 0x00, 0xa7, 0xd8, 0x57, 0xfc, - 0x15, 0xb6, 0x13, 0x06, 0x54, 0x58, 0x9c, 0x1a, 0x1a, 0x3a, 0x6c, 0xc9, 0x77, 0x39, 0xf3, 0xb0, - 0x25, 0xc2, 0xd9, 0x87, 0x6d, 0xe2, 0x3d, 0xcb, 0x7f, 0x0c, 0x72, 0x89, 0x77, 0xec, 0xb5, 0xb1, - 0x2e, 0x23, 0x68, 0xe1, 0xc6, 0x5e, 0xd0, 0x6c, 0x0d, 0x62, 0xf7, 0xdf, 0x78, 0x0d, 0xa2, 0xf0, - 0x09, 0x1a, 0x24, 0xdd, 0x4d, 0xfc, 0x16, 0xe0, 0x19, 0x17, 0xd3, 0x3c, 0xcb, 0x59, 0x1c, 0x27, - 0x48, 0xd3, 0xe1, 0xfc, 0x68, 0xd5, 0x95, 0xa7, 0x3b, 0x05, 0xee, 0xd9, 0x4e, 0x81, 0xfb, 0x63, - 0xa7, 0xc0, 0x7d, 0xb1, 0x5b, 0x48, 0x3d, 0xdb, 0x2d, 0xa4, 0x7e, 0xdd, 0x2d, 0xa4, 0xee, 0x97, - 0xa9, 0xd1, 0x7c, 0xcd, 0xf1, 0xb9, 0xb0, 0xa2, 0xb6, 0xb1, 0xec, 0xfd, 0x20, 0x35, 0x2c, 0xdf, - 0x90, 0x47, 0xd4, 0xcf, 0x67, 0xf6, 0xa8, 0xde, 0x3e, 0xe4, 0xfc, 0x28, 0x75, 0xfd, 0x9f, 0x00, - 0x00, 0x00, 0xff, 0xff, 0x1f, 0x41, 0x7f, 0xd7, 0x5e, 0x13, 0x00, 0x00, + // 1373 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x58, 0xcf, 0x73, 0xd3, 0xc6, + 0x17, 0x8f, 0x02, 0xc3, 0x8f, 0xcd, 0x17, 0x48, 0xf4, 0x85, 0xe0, 0x88, 0x62, 0x07, 0x01, 0x01, + 0x02, 0x91, 0x1a, 0x03, 0xed, 0x8c, 0xdb, 0x4b, 0x8c, 0x3d, 0x90, 0x69, 0x1c, 0x33, 0x4e, 0x52, + 0xa6, 0xf4, 0xa0, 0xca, 0xd6, 0x46, 0x56, 0x89, 0xb5, 0x46, 0xbb, 0x36, 0x66, 0x3a, 0xd3, 0x99, + 0x76, 0x7a, 0x60, 0x7a, 0xea, 0x4c, 0x4f, 0x3d, 0xf4, 0xd4, 0x4b, 0xdb, 0x13, 0x87, 0xde, 0x7a, + 0xe9, 0x91, 0x99, 0x5e, 0x98, 0x9e, 0x3a, 0x3d, 0xd0, 0x0e, 0x1c, 0x98, 0xfe, 0x03, 0xed, 0xb5, + 0xa3, 0x5d, 0x49, 0xac, 0xa4, 0x95, 0x6d, 0x68, 0x73, 0x89, 0xb5, 0xfb, 0x3e, 0xfb, 0xde, 0xe7, + 0x7d, 0xde, 0x6a, 0xf7, 0x45, 0x20, 0x87, 0x89, 0xe7, 0x58, 0x50, 0xc7, 0xc4, 0xbc, 0x03, 0x89, + 0x63, 0xea, 0x64, 0xa0, 0x75, 0x3d, 0x44, 0x90, 0x7c, 0x84, 0x59, 0xb4, 0xd0, 0xa2, 0x1c, 0x6f, + 0x21, 0xdc, 0x41, 0x58, 0xef, 0x60, 0x5b, 0xef, 0x2f, 0xfb, 0x3f, 0x0c, 0xa9, 0xcc, 0x98, 0x1d, + 0xc7, 0x45, 0x3a, 0xfd, 0x1b, 0x4c, 0x1d, 0xb5, 0x91, 0x8d, 0xe8, 0xa3, 0xee, 0x3f, 0x05, 0xb3, + 0xf9, 0xc0, 0x43, 0xd3, 0xc4, 0x50, 0xef, 0x2f, 0x37, 0x21, 0x31, 0x97, 0xf5, 0x16, 0x72, 0xdc, + 0xc0, 0x3e, 0xc7, 0xec, 0x06, 0x5b, 0xc8, 0x06, 0xe1, 0xd2, 0x24, 0xcf, 0xf0, 0x81, 0xd9, 0xd5, + 0x6f, 0x25, 0x70, 0xb8, 0x86, 0xed, 0x35, 0xe7, 0x6e, 0xcf, 0xb1, 0x36, 0x7c, 0x9b, 0x3c, 0x0b, + 0xf6, 0x51, 0x90, 0x97, 0x93, 0xe6, 0xa5, 0xf3, 0x07, 0x1b, 0xc1, 0x48, 0xde, 0x00, 0x87, 0x5c, + 0x93, 0x38, 0x7d, 0x68, 0x98, 0x1d, 0xd4, 0x73, 0x49, 0x6e, 0xd2, 0x37, 0x97, 0xb5, 0x47, 0x4f, + 0x0a, 0x13, 0xbf, 0x3d, 0x29, 0x2c, 0xd8, 0x0e, 0x69, 0xf7, 0x9a, 0x5a, 0x0b, 0x75, 0x02, 0x0a, + 0xc1, 0xcf, 0x12, 0xb6, 0xee, 0xe8, 0xe4, 0x7e, 0x17, 0x62, 0x6d, 0xd5, 0x25, 0x8d, 0xff, 0x31, + 0x27, 0x2b, 0xd4, 0x47, 0xe9, 0xc2, 0xa7, 0xcf, 0x1f, 0x2e, 0x06, 0x11, 0x3e, 0x7f, 0xfe, 0x70, + 0xf1, 0x78, 0x44, 0x34, 0xce, 0x2a, 0x27, 0xa9, 0x9f, 0x49, 0x60, 0x36, 0x3e, 0xd9, 0x80, 0xb8, + 0x8b, 0x5c, 0x0c, 0xe5, 0x6d, 0x70, 0x00, 0x13, 0x83, 0xa0, 0x3b, 0xd0, 0xa5, 0xa4, 0xa7, 0x8a, + 0x73, 0x5a, 0x20, 0x83, 0xaf, 0x99, 0x16, 0x68, 0xa6, 0x5d, 0x43, 0x8e, 0x5b, 0x7e, 0xdd, 0x27, + 0xfc, 0xfd, 0xef, 0x85, 0xf3, 0x63, 0x10, 0xf6, 0x17, 0xe0, 0xc6, 0x7e, 0x4c, 0x36, 0x7d, 0xdf, + 0xa5, 0xc9, 0x9c, 0xa4, 0xfe, 0xcc, 0x14, 0x6b, 0x40, 0x0b, 0xc2, 0x0e, 0x53, 0x4c, 0x01, 0x07, + 0x3c, 0x3a, 0x8c, 0x34, 0x8b, 0xc6, 0xf2, 0xbb, 0xe0, 0x48, 0x48, 0xed, 0xdf, 0xe9, 0x76, 0x28, + 0x20, 0xc1, 0x84, 0x63, 0x31, 0x5b, 0xd0, 0xe9, 0x43, 0x2f, 0xb7, 0x27, 0x8c, 0xc9, 0xc6, 0x4c, + 0xd4, 0x88, 0x42, 0x4a, 0x56, 0x8e, 0xba, 0xfa, 0x80, 0x89, 0xca, 0x4d, 0x45, 0xa2, 0xba, 0x20, + 0x28, 0xd5, 0xee, 0x09, 0x3b, 0xc5, 0x02, 0xd0, 0xbc, 0xd4, 0xaf, 0x24, 0x70, 0xb4, 0x86, 0xed, + 0x6b, 0xc8, 0xdd, 0x76, 0xbc, 0x4e, 0x05, 0xee, 0x40, 0xdb, 0x24, 0x0e, 0x72, 0xfd, 0x54, 0x51, + 0x17, 0x7a, 0x26, 0x41, 0x91, 0xbc, 0xe1, 0x58, 0x3e, 0x01, 0x0e, 0x7a, 0xb0, 0x85, 0x3c, 0xcb, + 0x70, 0x2c, 0x2a, 0xec, 0x5e, 0xaa, 0x03, 0xf2, 0xac, 0x55, 0x4b, 0x3e, 0x0e, 0xf6, 0x93, 0x81, + 0xd1, 0x36, 0x71, 0x3b, 0x90, 0x68, 0x1f, 0x19, 0xdc, 0x30, 0x71, 0xbb, 0xa4, 0x53, 0x81, 0x42, + 0x27, 0xbe, 0x40, 0x27, 0x79, 0x81, 0x52, 0x14, 0xd4, 0x3c, 0x78, 0x4d, 0x34, 0x1f, 0x6a, 0xa5, + 0x7e, 0xcd, 0x64, 0x0c, 0x00, 0x5b, 0xae, 0xb5, 0x9b, 0xec, 0x97, 0x53, 0xec, 0x0b, 0x02, 0xf6, + 0x3c, 0x09, 0x75, 0x1e, 0xe4, 0xc5, 0x96, 0x28, 0x83, 0xef, 0x24, 0x3e, 0xc5, 0x2d, 0xb7, 0x89, + 0x5c, 0x0b, 0x5a, 0xb4, 0x32, 0x1b, 0xf7, 0x20, 0xec, 0xee, 0x42, 0x1e, 0x6f, 0xa6, 0xf2, 0x38, + 0x2b, 0xcc, 0x23, 0x49, 0x45, 0x5d, 0x00, 0x67, 0x86, 0xd9, 0xa3, 0x9c, 0xfe, 0x96, 0xc0, 0x5c, + 0x0d, 0xdb, 0x2b, 0xd6, 0x87, 0x3d, 0x4c, 0x82, 0xaa, 0x41, 0xab, 0x6c, 0xee, 0x98, 0x6e, 0x0b, + 0x0e, 0x4d, 0xe8, 0x7d, 0x30, 0xf3, 0x42, 0x23, 0x03, 0x6d, 0x6f, 0x63, 0xf8, 0xaa, 0xef, 0xed, + 0xf4, 0x0b, 0x47, 0x75, 0xea, 0x47, 0xbe, 0x08, 0x66, 0xfa, 0xe6, 0x8e, 0x63, 0xf9, 0x91, 0x0c, + 0xd3, 0xb2, 0x3c, 0x88, 0x71, 0x20, 0xcd, 0x74, 0x64, 0x58, 0x61, 0xf3, 0xa5, 0x2b, 0x29, 0x91, + 0x54, 0x5e, 0x24, 0x71, 0x6e, 0xea, 0x69, 0x70, 0x2a, 0xd3, 0x18, 0xc9, 0xf3, 0xe7, 0x24, 0x50, + 0x6b, 0xd8, 0xde, 0xea, 0x5a, 0x26, 0x81, 0xab, 0xae, 0x0b, 0x3d, 0xff, 0x18, 0xe8, 0x74, 0xe9, + 0xbe, 0x30, 0x09, 0x2c, 0xa3, 0x9e, 0x6b, 0x61, 0x39, 0x07, 0xf6, 0xb7, 0x3c, 0xc8, 0xc9, 0x14, + 0x0e, 0xe5, 0x7b, 0x60, 0xae, 0xe3, 0xb8, 0x86, 0xe3, 0x2f, 0x35, 0xbc, 0x68, 0xad, 0xe1, 0x99, + 0x04, 0x06, 0x6a, 0xbd, 0xfd, 0x12, 0x6a, 0x55, 0x60, 0xeb, 0x97, 0x1f, 0x96, 0x40, 0x70, 0xbe, + 0x54, 0x60, 0xab, 0x31, 0xdb, 0x71, 0x5c, 0x01, 0x31, 0x1a, 0xd8, 0x1c, 0x64, 0x04, 0xde, 0xf3, + 0x9f, 0x04, 0x36, 0x07, 0x82, 0xc0, 0x6c, 0xcb, 0x86, 0xf9, 0xfb, 0xc5, 0x58, 0xe0, 0x8b, 0xc1, + 0x94, 0x14, 0x89, 0xa8, 0x5e, 0x02, 0x8b, 0xa3, 0xa5, 0x8e, 0x2a, 0x73, 0x1b, 0xcc, 0xd0, 0x43, + 0x19, 0xf7, 0x3a, 0xf0, 0x06, 0xc2, 0xe4, 0x36, 0x72, 0x61, 0x76, 0x1d, 0x4a, 0x17, 0x93, 0xac, + 0x94, 0xf8, 0x71, 0xcf, 0xbb, 0x51, 0x4f, 0xd0, 0x77, 0x22, 0x3e, 0x19, 0x05, 0x6e, 0x83, 0x1c, + 0x35, 0x6e, 0x7b, 0x10, 0xb7, 0x13, 0xa2, 0x67, 0xc7, 0x2f, 0x26, 0xe3, 0x9f, 0x8a, 0xc7, 0x17, + 0x78, 0x53, 0x55, 0x30, 0x9f, 0x65, 0x8b, 0xd8, 0xfc, 0xc4, 0xce, 0xa4, 0x7a, 0x1f, 0x7a, 0xf7, + 0x3c, 0x87, 0x40, 0xfe, 0xe0, 0xf5, 0x0f, 0x97, 0x21, 0x5b, 0x73, 0x3d, 0xf6, 0x02, 0xb3, 0xb3, + 0x88, 0x6e, 0xc9, 0xa9, 0xe2, 0x29, 0x2d, 0xd1, 0xa1, 0x69, 0x49, 0xbf, 0xfc, 0x3b, 0xcb, 0x66, + 0x4a, 0x6f, 0x24, 0x53, 0x8c, 0x1d, 0x55, 0x99, 0x0c, 0x83, 0xa3, 0x2a, 0xd3, 0x1e, 0xa5, 0xfa, + 0xa3, 0x04, 0x4e, 0xf0, 0x40, 0x76, 0xaa, 0x39, 0xae, 0x3d, 0x32, 0xd3, 0x77, 0xc0, 0x74, 0x2f, + 0x04, 0xc7, 0x13, 0x9d, 0x4f, 0x25, 0x9a, 0xf0, 0xda, 0x38, 0xd2, 0x8b, 0x4f, 0x94, 0xae, 0x26, + 0xd3, 0x3c, 0x23, 0x4c, 0x33, 0xe1, 0x47, 0x3d, 0x0b, 0x4e, 0x0f, 0x31, 0x67, 0xd6, 0x93, 0x2b, + 0xfb, 0x18, 0xf5, 0xe4, 0xdf, 0xf3, 0xe1, 0xf5, 0x4c, 0xfa, 0x6d, 0x4c, 0x7b, 0x89, 0x99, 0x71, + 0xeb, 0x99, 0xf4, 0x94, 0xac, 0x67, 0x2a, 0x52, 0x98, 0xea, 0x47, 0xe0, 0x58, 0x0d, 0xdb, 0x1b, + 0x90, 0xd4, 0x83, 0x93, 0x3b, 0x38, 0xcf, 0x69, 0x77, 0xed, 0xd8, 0x2e, 0xd7, 0x5d, 0xd3, 0x51, + 0xec, 0x36, 0x9a, 0x8c, 0xdf, 0x46, 0x25, 0x8d, 0x35, 0xc9, 0x14, 0xe8, 0x73, 0xcd, 0xf3, 0x5c, + 0xd3, 0x31, 0xd4, 0x02, 0x38, 0x29, 0x34, 0x84, 0xec, 0x16, 0xef, 0x82, 0xd9, 0x30, 0x05, 0xb3, + 0xb9, 0x03, 0x19, 0xf7, 0xcd, 0xfb, 0x5d, 0xff, 0x52, 0x9c, 0x6d, 0x54, 0xaf, 0xd5, 0x1b, 0x15, + 0x63, 0xf3, 0xbd, 0x9b, 0x55, 0xa3, 0x52, 0x5d, 0xab, 0x5e, 0x5f, 0xd9, 0x5c, 0xad, 0xaf, 0x4f, + 0x4f, 0xc8, 0x73, 0xe0, 0x18, 0x6f, 0xdb, 0x5a, 0x2f, 0xd7, 0xd7, 0x2b, 0xab, 0xeb, 0xd7, 0xa7, + 0xa5, 0xe4, 0xb2, 0x46, 0xb5, 0x52, 0xad, 0xdd, 0xa4, 0xcb, 0x26, 0x95, 0xbd, 0x0f, 0xbe, 0xc9, + 0x4f, 0x14, 0xff, 0x9a, 0x02, 0x7b, 0x6a, 0xd8, 0x96, 0x6f, 0x81, 0x29, 0xfe, 0x9f, 0x8d, 0x42, + 0xaa, 0x78, 0xf1, 0x16, 0x5f, 0x39, 0x37, 0x02, 0x10, 0xb5, 0xab, 0xb7, 0xc0, 0x14, 0xdf, 0x93, + 0x0b, 0x1d, 0x73, 0x00, 0xb1, 0x63, 0x51, 0x1f, 0xec, 0x80, 0x99, 0x74, 0x4f, 0x7a, 0x56, 0xb4, + 0x3a, 0x05, 0x53, 0x96, 0xc6, 0x82, 0x45, 0xa1, 0x10, 0xf8, 0xbf, 0xa8, 0x85, 0x3c, 0x37, 0xc4, + 0x0b, 0x0f, 0x54, 0xf4, 0x31, 0x81, 0x51, 0xc0, 0x4f, 0x24, 0x30, 0x97, 0xdd, 0xf2, 0x2d, 0x0d, + 0x75, 0x97, 0x84, 0x2b, 0x57, 0x5f, 0x0a, 0x1e, 0x71, 0x18, 0x80, 0xd9, 0x8c, 0x0e, 0x6d, 0x51, + 0xe4, 0x50, 0x8c, 0x55, 0x8a, 0xe3, 0x63, 0xa3, 0xc8, 0x5f, 0x4a, 0xa0, 0x30, 0xaa, 0xfb, 0xb9, + 0x2c, 0xf2, 0x3b, 0x62, 0x91, 0xf2, 0xd6, 0x2b, 0x2c, 0x8a, 0x58, 0x7d, 0x00, 0x0e, 0x27, 0x6e, + 0x7e, 0x55, 0xbc, 0x55, 0x79, 0x8c, 0xb2, 0x38, 0x1a, 0x13, 0x45, 0xe8, 0x81, 0x63, 0xe2, 0x2b, + 0xfe, 0x82, 0xd8, 0x89, 0x00, 0xaa, 0x2c, 0x8f, 0x0d, 0x8d, 0x6d, 0xb6, 0xec, 0xbb, 0x5c, 0xb8, + 0xd9, 0x32, 0xe1, 0xe2, 0xcd, 0x36, 0xf2, 0x9e, 0x95, 0x3f, 0x06, 0xb9, 0xcc, 0x3b, 0xf6, 0xd2, + 0x50, 0x97, 0x09, 0xb4, 0x72, 0xe5, 0x65, 0xd0, 0x62, 0x0d, 0x52, 0xf7, 0xdf, 0x70, 0x0d, 0x92, + 0xf0, 0x11, 0x1a, 0x64, 0xdd, 0x4d, 0xf2, 0x0e, 0x90, 0x05, 0x17, 0xd3, 0x82, 0xc8, 0x59, 0x1a, + 0xa7, 0x68, 0xe3, 0xe1, 0xc2, 0x68, 0xe5, 0xb5, 0x47, 0x4f, 0xf3, 0xd2, 0xe3, 0xa7, 0x79, 0xe9, + 0x8f, 0xa7, 0x79, 0xe9, 0x8b, 0x67, 0xf9, 0x89, 0xc7, 0xcf, 0xf2, 0x13, 0xbf, 0x3e, 0xcb, 0x4f, + 0xdc, 0x2e, 0x72, 0xad, 0xf9, 0x06, 0xf5, 0xb9, 0xb4, 0x66, 0x36, 0xb1, 0x1e, 0x7c, 0xb2, 0xea, + 0x17, 0xaf, 0xe8, 0x03, 0xee, 0x03, 0x9b, 0xdf, 0xaa, 0x37, 0xf7, 0xd1, 0xcf, 0x56, 0x97, 0xff, + 0x09, 0x00, 0x00, 0xff, 0xff, 0xf7, 0x04, 0xe5, 0xde, 0x80, 0x13, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -1987,6 +2002,13 @@ func (m *MsgRedeemStake) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if len(m.Receiver) > 0 { + i -= len(m.Receiver) + copy(dAtA[i:], m.Receiver) + i = encodeVarintTx(dAtA, i, uint64(len(m.Receiver))) + i-- + dAtA[i] = 0x1a + } { size := m.StTokenAmount.Size() i -= size @@ -2788,6 +2810,10 @@ func (m *MsgRedeemStake) Size() (n int) { } l = m.StTokenAmount.Size() n += 1 + l + sovTx(uint64(l)) + l = len(m.Receiver) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } return n } @@ -3391,6 +3417,38 @@ func (m *MsgRedeemStake) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Receiver", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Receiver = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipTx(dAtA[iNdEx:])