From 3144fa2f7a7998ea34a9aa001d6d365d649e4548 Mon Sep 17 00:00:00 2001 From: Connor Barr Date: Wed, 13 Nov 2024 12:15:06 +0000 Subject: [PATCH 01/20] feat: added distribution messages to std crate --- Cargo.lock | 2 + .../andromeda-validator-staking/Cargo.toml | 2 +- packages/std/Cargo.toml | 5 + packages/std/src/common/distribution.rs | 103 ++++++++++++++++++ packages/std/src/common/mod.rs | 2 + 5 files changed, 113 insertions(+), 1 deletion(-) create mode 100644 packages/std/src/common/distribution.rs diff --git a/Cargo.lock b/Cargo.lock index 3f9202c39..7abdb8abb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -717,6 +717,8 @@ dependencies = [ "enum-repr", "hex", "lazy_static", + "osmosis-std-derive 0.15.3", + "prost 0.11.9", "regex", "schemars", "semver", diff --git a/contracts/finance/andromeda-validator-staking/Cargo.toml b/contracts/finance/andromeda-validator-staking/Cargo.toml index f4e5a3ee6..dcbd1a8fc 100644 --- a/contracts/finance/andromeda-validator-staking/Cargo.toml +++ b/contracts/finance/andromeda-validator-staking/Cargo.toml @@ -21,7 +21,7 @@ cw-storage-plus = { workspace = true } cw2 = { workspace = true } serde = { workspace = true } -andromeda-std = { workspace = true } +andromeda-std = { workspace = true, features = ["distribution"] } andromeda-finance = { workspace = true } enum-repr = { workspace = true } chrono = "0.3" diff --git a/packages/std/Cargo.toml b/packages/std/Cargo.toml index cba0750ca..1f3edcfa7 100644 --- a/packages/std/Cargo.toml +++ b/packages/std/Cargo.toml @@ -11,6 +11,7 @@ primitive = [] instantiate = [] rates = ["andromeda-macros/rates"] deploy = [] +distribution = ["prost", "osmosis-std-derive"] [lib] crate-type = ["cdylib", "rlib"] @@ -39,6 +40,10 @@ serde-json-wasm = "0.5.0" enum-repr = { workspace = true } sha2 = "0.10.8" cw-orch = { workspace = true } +osmosis-std-derive = { version = "0.15.3", optional = true } +prost = { version = "0.11.2", default-features = false, features = [ + "prost-derive", +], optional = true } [dev-dependencies] cw-multi-test = { version = "1.0.0" } diff --git a/packages/std/src/common/distribution.rs b/packages/std/src/common/distribution.rs new file mode 100644 index 000000000..8a0a7becc --- /dev/null +++ b/packages/std/src/common/distribution.rs @@ -0,0 +1,103 @@ +use osmosis_std_derive::CosmwasmExt; + +#[derive( + Clone, + PartialEq, + Eq, + ::prost::Message, + serde::Serialize, + serde::Deserialize, + schemars::JsonSchema, + CosmwasmExt, +)] +#[proto_message(type_url = "/andromeda.distribution.v1beta1.MsgSetWithdrawAddress")] +pub struct MsgSetWithdrawAddress { + #[prost(string, tag = "1")] + pub delegator_address: ::prost::alloc::string::String, + #[prost(string, tag = "2")] + pub withdraw_address: ::prost::alloc::string::String, +} + +#[derive( + Clone, + PartialEq, + Eq, + ::prost::Message, + serde::Serialize, + serde::Deserialize, + schemars::JsonSchema, + CosmwasmExt, +)] +#[proto_message(type_url = "/andromeda.distribution.v1beta1.MsgSetWithdrawAddressResponse")] +pub struct MsgSetWithdrawAddressResponse {} + +#[derive( + Clone, + PartialEq, + Eq, + ::prost::Message, + serde::Serialize, + serde::Deserialize, + schemars::JsonSchema, + CosmwasmExt, +)] +#[proto_message(type_url = "/andromeda.distribution.v1beta1.MsgWithdrawDelegatorReward")] +pub struct MsgWithdrawDelegatorReward { + #[prost(string, tag = "1")] + pub delegator_address: ::prost::alloc::string::String, + #[prost(string, tag = "2")] + pub validator_address: ::prost::alloc::string::String, +} + +#[derive( + Clone, + PartialEq, + Eq, + ::prost::Message, + serde::Serialize, + serde::Deserialize, + schemars::JsonSchema, + CosmwasmExt, +)] +#[proto_message(type_url = "/andromeda.distribution.v1beta1.MsgWithdrawDelegatorRewardResponse")] +pub struct MsgWithdrawDelegatorRewardResponse {} + +#[derive( + Clone, + PartialEq, + Eq, + ::prost::Message, + ::serde::Serialize, + ::serde::Deserialize, + schemars::JsonSchema, + CosmwasmExt, +)] +#[proto_message(type_url = "/cosmos.base.v1beta1.Coin")] +pub struct Coin { + #[prost(string, tag = "1")] + pub denom: ::prost::alloc::string::String, + #[prost(string, tag = "2")] + pub amount: ::prost::alloc::string::String, +} + +#[derive( + Clone, + PartialEq, + Eq, + ::prost::Message, + serde::Serialize, + serde::Deserialize, + schemars::JsonSchema, + CosmwasmExt, +)] +#[proto_message(type_url = "/cosmos.staking.v1beta1.MsgCancelUnbondingDelegation")] +pub struct MsgCancelUnbondingDelegation { + #[prost(string, tag = "1")] + pub delegator_address: ::prost::alloc::string::String, + #[prost(string, tag = "2")] + pub validator_address: ::prost::alloc::string::String, + #[prost(message, tag = "3")] + pub amount: ::core::option::Option, + #[prost(uint64, tag = "4")] + pub creation_height: u64, +} diff --git a/packages/std/src/common/mod.rs b/packages/std/src/common/mod.rs index 350c38ff6..73ec42cdc 100644 --- a/packages/std/src/common/mod.rs +++ b/packages/std/src/common/mod.rs @@ -1,6 +1,8 @@ pub mod actions; pub mod context; pub mod denom; +#[cfg(feature = "distribution")] +pub mod distribution; pub mod expiration; pub mod migration; pub mod milliseconds; From a7bfa50eecec55208b7e896864dead089ff1e607 Mon Sep 17 00:00:00 2001 From: Connor Barr Date: Wed, 13 Nov 2024 12:27:52 +0000 Subject: [PATCH 02/20] fix: validator staking distribution message for andromeda chain --- .../src/contract.rs | 22 +++++++++++++++---- contracts/os/andromeda-kernel/src/mock.rs | 2 +- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/contracts/finance/andromeda-validator-staking/src/contract.rs b/contracts/finance/andromeda-validator-staking/src/contract.rs index fe3601287..713b6d0f1 100644 --- a/contracts/finance/andromeda-validator-staking/src/contract.rs +++ b/contracts/finance/andromeda-validator-staking/src/contract.rs @@ -16,8 +16,9 @@ use andromeda_std::{ ado_base::{InstantiateMsg as BaseInstantiateMsg, MigrateMsg}, ado_contract::ADOContract, amp::AndrAddr, - common::{context::ExecuteContext, encode_binary}, + common::{context::ExecuteContext, distribution::MsgWithdrawDelegatorReward, encode_binary}, error::ContractError, + os::aos_querier::AOSQuerier, }; use enum_repr::EnumRepr; @@ -246,10 +247,23 @@ fn execute_claim(ctx: ExecuteContext, validator: Option) -> Result Box> { pub fn mock_kernel_instantiate_message(owner: Option) -> InstantiateMsg { InstantiateMsg { owner, - chain_name: "andromeda".to_string(), + chain_name: "andromeda-local".to_string(), } } From 8fe3f9b62fdd5d2b881099318667ab8723bf46de Mon Sep 17 00:00:00 2001 From: Connor Barr Date: Wed, 13 Nov 2024 12:31:40 +0000 Subject: [PATCH 03/20] chore: changelog and version bumps --- CHANGELOG.md | 1 + Cargo.lock | 2 +- contracts/finance/andromeda-validator-staking/Cargo.toml | 2 +- packages/std/Cargo.toml | 2 +- 4 files changed, 4 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 31f602905..442f1707b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Vesting: Added validation to the instantiation process [(#583)](https://github.com/andromedaprotocol/andromeda-core/pull/583) - Fix precision issue with vestings claim batch method [(#555)](https://github.com/andromedaprotocol/andromeda-core/pull/555) +- (validator-staking) fix: validator staking distribution message for andromeda chain [(#618)](https://github.com/andromedaprotocol/andromeda-core/pull/618) ### Removed diff --git a/Cargo.lock b/Cargo.lock index 7abdb8abb..d3aebc23e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -811,7 +811,7 @@ dependencies = [ [[package]] name = "andromeda-validator-staking" -version = "0.2.3" +version = "0.2.3-b.1" dependencies = [ "andromeda-finance", "andromeda-std", diff --git a/contracts/finance/andromeda-validator-staking/Cargo.toml b/contracts/finance/andromeda-validator-staking/Cargo.toml index dcbd1a8fc..34bee2de0 100644 --- a/contracts/finance/andromeda-validator-staking/Cargo.toml +++ b/contracts/finance/andromeda-validator-staking/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "andromeda-validator-staking" -version = "0.2.3" +version = "0.2.3-b.1" edition = "2021" rust-version = "1.75.0" diff --git a/packages/std/Cargo.toml b/packages/std/Cargo.toml index 1f3edcfa7..3d010d03e 100644 --- a/packages/std/Cargo.toml +++ b/packages/std/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "andromeda-std" -version = "1.2.4" +version = "1.2.4-b.1" edition = "2021" rust-version = "1.75.0" description = "The standard library for creating an Andromeda Digital Object" From be80f283ef4cd9218a6e127b89ac3fddb2dec2aa Mon Sep 17 00:00:00 2001 From: Connor Barr Date: Wed, 13 Nov 2024 12:35:03 +0000 Subject: [PATCH 04/20] chore: lint --- Cargo.lock | 2 +- Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d3aebc23e..ca41a25df 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -699,7 +699,7 @@ dependencies = [ [[package]] name = "andromeda-std" -version = "1.2.4" +version = "1.2.4-b.1" dependencies = [ "andromeda-macros", "cosmwasm-schema", diff --git a/Cargo.toml b/Cargo.toml index fa05ebd17..8eea7079e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -29,7 +29,7 @@ panic = 'abort' strip = true [workspace.dependencies] -andromeda-std = { path = "./packages/std", default-features = false, version = "1.0.0", features = [ +andromeda-std = { path = "./packages/std", default-features = false, features = [ "deploy", ] } andromeda-macros = { path = "./packages/std/macros", default-features = false, version = "1.0.0" } From f061d167bed2b0bcd7d0b5f2e4693fa76ecd48e9 Mon Sep 17 00:00:00 2001 From: Joe Monem Date: Thu, 14 Nov 2024 15:08:55 +0200 Subject: [PATCH 05/20] fix: use ok_or for accessing attributes and unstaking queue --- Cargo.lock | 2 +- .../finance/andromeda-validator-staking/Cargo.toml | 2 +- .../andromeda-validator-staking/src/contract.rs | 10 ++++++++-- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3f9202c39..56b38a9b4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -809,7 +809,7 @@ dependencies = [ [[package]] name = "andromeda-validator-staking" -version = "0.2.3" +version = "0.2.3-b.1" dependencies = [ "andromeda-finance", "andromeda-std", diff --git a/contracts/finance/andromeda-validator-staking/Cargo.toml b/contracts/finance/andromeda-validator-staking/Cargo.toml index f4e5a3ee6..8ef99f14c 100644 --- a/contracts/finance/andromeda-validator-staking/Cargo.toml +++ b/contracts/finance/andromeda-validator-staking/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "andromeda-validator-staking" -version = "0.2.3" +version = "0.2.3-b.1" edition = "2021" rust-version = "1.75.0" diff --git a/contracts/finance/andromeda-validator-staking/src/contract.rs b/contracts/finance/andromeda-validator-staking/src/contract.rs index fe3601287..94bb080b2 100644 --- a/contracts/finance/andromeda-validator-staking/src/contract.rs +++ b/contracts/finance/andromeda-validator-staking/src/contract.rs @@ -371,7 +371,11 @@ pub fn on_validator_unstake(deps: DepsMut, msg: Reply) -> Result Result Date: Thu, 14 Nov 2024 15:13:43 +0200 Subject: [PATCH 06/20] ref: simplify addition to the unstaking_queue --- .../andromeda-validator-staking/src/contract.rs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/contracts/finance/andromeda-validator-staking/src/contract.rs b/contracts/finance/andromeda-validator-staking/src/contract.rs index 94bb080b2..07f0f7fcf 100644 --- a/contracts/finance/andromeda-validator-staking/src/contract.rs +++ b/contracts/finance/andromeda-validator-staking/src/contract.rs @@ -192,11 +192,12 @@ fn execute_unstake( amount: fund.clone(), }); - let mut unstaking_queue = UNSTAKING_QUEUE.load(deps.storage).unwrap_or_default(); - unstaking_queue.push(UnstakingTokens { - fund, - payout_at: Timestamp::default(), - }); + let unstaking_queue = UNSTAKING_QUEUE + .load(deps.storage) + .unwrap_or(vec![UnstakingTokens { + fund, + payout_at: Timestamp::default(), + }]); UNSTAKING_QUEUE.save(deps.storage, &unstaking_queue)?; From 26c8a7faeaf828dc15c0e8a01217685fddf8471a Mon Sep 17 00:00:00 2001 From: Joe Monem Date: Thu, 14 Nov 2024 15:26:52 +0200 Subject: [PATCH 07/20] chore: version bump --- Cargo.lock | 2 +- contracts/finance/andromeda-validator-staking/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ca41a25df..5359a929e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -811,7 +811,7 @@ dependencies = [ [[package]] name = "andromeda-validator-staking" -version = "0.2.3-b.1" +version = "0.2.3-b.2" dependencies = [ "andromeda-finance", "andromeda-std", diff --git a/contracts/finance/andromeda-validator-staking/Cargo.toml b/contracts/finance/andromeda-validator-staking/Cargo.toml index 34bee2de0..f8d2554a0 100644 --- a/contracts/finance/andromeda-validator-staking/Cargo.toml +++ b/contracts/finance/andromeda-validator-staking/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "andromeda-validator-staking" -version = "0.2.3-b.1" +version = "0.2.3-b.2" edition = "2021" rust-version = "1.75.0" From 41e1b25b2d5006876b43859e0b10493f2f960d7d Mon Sep 17 00:00:00 2001 From: Joe Monem Date: Fri, 15 Nov 2024 15:29:14 +0200 Subject: [PATCH 08/20] feat: query default validator --- .../andromeda-validator-staking/src/contract.rs | 10 +++++++++- packages/andromeda-finance/src/validator_staking.rs | 8 ++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/contracts/finance/andromeda-validator-staking/src/contract.rs b/contracts/finance/andromeda-validator-staking/src/contract.rs index 3bafa4048..19cff8e4d 100644 --- a/contracts/finance/andromeda-validator-staking/src/contract.rs +++ b/contracts/finance/andromeda-validator-staking/src/contract.rs @@ -9,7 +9,8 @@ use cosmwasm_std::{ use cw2::set_contract_version; use andromeda_finance::validator_staking::{ - is_validator, ExecuteMsg, InstantiateMsg, QueryMsg, UnstakingTokens, + is_validator, ExecuteMsg, GetDefaultValidatorResponse, InstantiateMsg, QueryMsg, + UnstakingTokens, }; use andromeda_std::{ @@ -107,6 +108,8 @@ pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> Result encode_binary(&query_unstaked_tokens(deps)?), + QueryMsg::DefaultValidator {} => encode_binary(&query_default_validator(deps)?), + _ => ADOContract::default().query(deps, env, msg), } } @@ -369,6 +372,11 @@ fn query_unstaked_tokens(deps: Deps) -> Result, ContractErr Ok(res) } +fn query_default_validator(deps: Deps) -> Result { + let default_validator = DEFAULT_VALIDATOR.load(deps.storage)?; + Ok(GetDefaultValidatorResponse { default_validator }) +} + #[cfg_attr(not(feature = "library"), entry_point)] pub fn reply(deps: DepsMut, _env: Env, msg: Reply) -> Result { match ReplyId::from_repr(msg.id) { diff --git a/packages/andromeda-finance/src/validator_staking.rs b/packages/andromeda-finance/src/validator_staking.rs index e3fbd3437..606dcd393 100644 --- a/packages/andromeda-finance/src/validator_staking.rs +++ b/packages/andromeda-finance/src/validator_staking.rs @@ -47,6 +47,9 @@ pub enum QueryMsg { #[returns(Option>)] UnstakedTokens {}, + + #[returns(GetDefaultValidatorResponse)] + DefaultValidator {}, } impl InstantiateMsg { @@ -62,3 +65,8 @@ pub fn is_validator(deps: &DepsMut, validator: &Addr) -> Result Date: Fri, 15 Nov 2024 15:39:25 +0200 Subject: [PATCH 09/20] chore: improve ContractError naming --- .../finance/andromeda-validator-staking/src/contract.rs | 4 ++-- packages/std/src/error.rs | 6 ++++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/contracts/finance/andromeda-validator-staking/src/contract.rs b/contracts/finance/andromeda-validator-staking/src/contract.rs index 19cff8e4d..c70e70e41 100644 --- a/contracts/finance/andromeda-validator-staking/src/contract.rs +++ b/contracts/finance/andromeda-validator-staking/src/contract.rs @@ -397,7 +397,7 @@ pub fn on_validator_unstake(deps: DepsMut, msg: Reply) -> Result Result Date: Fri, 15 Nov 2024 16:08:29 +0200 Subject: [PATCH 10/20] feat: redelegate function --- .../src/contract.rs | 55 +++++++++++++++++++ .../src/validator_staking.rs | 5 ++ packages/std/src/error.rs | 3 + 3 files changed, 63 insertions(+) diff --git a/contracts/finance/andromeda-validator-staking/src/contract.rs b/contracts/finance/andromeda-validator-staking/src/contract.rs index c70e70e41..291061503 100644 --- a/contracts/finance/andromeda-validator-staking/src/contract.rs +++ b/contracts/finance/andromeda-validator-staking/src/contract.rs @@ -84,6 +84,11 @@ pub fn handle_execute(ctx: ExecuteContext, msg: ExecuteMsg) -> Result execute_stake(ctx, validator), ExecuteMsg::Unstake { validator, amount } => execute_unstake(ctx, validator, amount), ExecuteMsg::Claim { validator } => execute_claim(ctx, validator), + ExecuteMsg::Redelegate { + src_validator, + dst_validator, + amount, + } => execute_redelegate(ctx, src_validator, dst_validator, amount), ExecuteMsg::WithdrawFunds { denom, recipient } => { execute_withdraw_fund(ctx, denom, recipient) } @@ -148,6 +153,56 @@ fn execute_stake(ctx: ExecuteContext, validator: Option) -> Result, + dst_validator: Addr, + amount: Option, +) -> Result { + let ExecuteContext { deps, env, .. } = ctx; + let src_validator = src_validator.unwrap_or(DEFAULT_VALIDATOR.load(deps.storage)?); + + // Check if the source and destination validators are valid + is_validator(&deps, &src_validator)?; + is_validator(&deps, &dst_validator)?; + + // Get redelegation amount + let Some(full_delegation) = deps + .querier + .query_delegation(env.contract.address.to_string(), src_validator.to_string())? + else { + return Err(ContractError::InvalidValidatorOperation { + operation: "Redelegate".to_string(), + validator: src_validator.to_string(), + }); + }; + let redelegation_amount = match amount { + Some(amount) => { + if amount > full_delegation.amount.amount { + return Err(ContractError::InvalidRedelegationAmount { + amount: amount.to_string(), + max: full_delegation.amount.amount.to_string(), + }); + } + amount + } + None => full_delegation.amount.amount, + }; + + let res = Response::new() + .add_message(StakingMsg::Redelegate { + src_validator: src_validator.clone().into_string(), + dst_validator: dst_validator.clone().into_string(), + amount: coin(redelegation_amount.u128(), full_delegation.amount.denom), + }) + .add_attribute("action", "redelegation") + .add_attribute("from", src_validator.to_string()) + .add_attribute("to", dst_validator.to_string()) + .add_attribute("amount", redelegation_amount.to_string()); + + Ok(res) +} + fn execute_unstake( ctx: ExecuteContext, validator: Option, diff --git a/packages/andromeda-finance/src/validator_staking.rs b/packages/andromeda-finance/src/validator_staking.rs index 606dcd393..f9f1798de 100644 --- a/packages/andromeda-finance/src/validator_staking.rs +++ b/packages/andromeda-finance/src/validator_staking.rs @@ -20,6 +20,11 @@ pub enum ExecuteMsg { validator: Option, amount: Option, }, + Redelegate { + src_validator: Option, + dst_validator: Addr, + amount: Option, + }, Claim { validator: Option, }, diff --git a/packages/std/src/error.rs b/packages/std/src/error.rs index 47601ba22..0bb2fd3ec 100644 --- a/packages/std/src/error.rs +++ b/packages/std/src/error.rs @@ -93,6 +93,9 @@ pub enum ContractError { #[error("RewardTooLow")] RewardTooLow {}, + #[error("InvalidRedelegationAmount. Got {{amount}}, full delegation: {{max}}")] + InvalidRedelegationAmount { amount: String, max: String }, + #[error("LockedNFT")] LockedNFT {}, From e7923098f0acf31776ffc5083649c855ad313c76 Mon Sep 17 00:00:00 2001 From: Joe Monem Date: Mon, 18 Nov 2024 09:36:35 +0200 Subject: [PATCH 11/20] feat: restaking --- Cargo.lock | 2 +- .../andromeda-validator-staking/Cargo.toml | 2 +- .../src/contract.rs | 74 ++++++++++++++++--- .../andromeda-validator-staking/src/mock.rs | 5 +- .../andromeda-validator-staking/src/state.rs | 4 +- .../src/testing/tests.rs | 1 + ibc-tests/tests/validator_staking.rs | 2 + .../src/validator_staking.rs | 2 + 8 files changed, 76 insertions(+), 16 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5359a929e..26dff70bf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -811,7 +811,7 @@ dependencies = [ [[package]] name = "andromeda-validator-staking" -version = "0.2.3-b.2" +version = "0.3.0-b.1" dependencies = [ "andromeda-finance", "andromeda-std", diff --git a/contracts/finance/andromeda-validator-staking/Cargo.toml b/contracts/finance/andromeda-validator-staking/Cargo.toml index f8d2554a0..240461e82 100644 --- a/contracts/finance/andromeda-validator-staking/Cargo.toml +++ b/contracts/finance/andromeda-validator-staking/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "andromeda-validator-staking" -version = "0.2.3-b.2" +version = "0.3.0-b.1" edition = "2021" rust-version = "1.75.0" diff --git a/contracts/finance/andromeda-validator-staking/src/contract.rs b/contracts/finance/andromeda-validator-staking/src/contract.rs index 291061503..8b3be23a0 100644 --- a/contracts/finance/andromeda-validator-staking/src/contract.rs +++ b/contracts/finance/andromeda-validator-staking/src/contract.rs @@ -1,5 +1,5 @@ use crate::{ - state::{DEFAULT_VALIDATOR, UNSTAKING_QUEUE}, + state::{DEFAULT_VALIDATOR, RESTAKING_QUEUE, UNSTAKING_QUEUE}, util::decode_unstaking_response_data, }; use cosmwasm_std::{ @@ -32,6 +32,7 @@ const CONTRACT_VERSION: &str = env!("CARGO_PKG_VERSION"); pub enum ReplyId { ValidatorUnstake = 201, SetWithdrawAddress = 202, + RestakeReward = 203, } #[cfg_attr(not(feature = "library"), entry_point)] @@ -83,7 +84,7 @@ pub fn handle_execute(ctx: ExecuteContext, msg: ExecuteMsg) -> Result execute_stake(ctx, validator), ExecuteMsg::Unstake { validator, amount } => execute_unstake(ctx, validator, amount), - ExecuteMsg::Claim { validator } => execute_claim(ctx, validator), + ExecuteMsg::Claim { validator, restake } => execute_claim(ctx, validator, restake), ExecuteMsg::Redelegate { src_validator, dst_validator, @@ -160,10 +161,15 @@ fn execute_redelegate( amount: Option, ) -> Result { let ExecuteContext { deps, env, .. } = ctx; - let src_validator = src_validator.unwrap_or(DEFAULT_VALIDATOR.load(deps.storage)?); + let src_validator = match src_validator { + Some(addr) => { + is_validator(&deps, &addr)?; + addr + } + None => DEFAULT_VALIDATOR.load(deps.storage)?, + }; - // Check if the source and destination validators are valid - is_validator(&deps, &src_validator)?; + // Check if the destination validator is valid is_validator(&deps, &dst_validator)?; // Get redelegation amount @@ -272,7 +278,11 @@ fn execute_unstake( Ok(res) } -fn execute_claim(ctx: ExecuteContext, validator: Option) -> Result { +fn execute_claim( + ctx: ExecuteContext, + validator: Option, + restake: Option, +) -> Result { let ExecuteContext { deps, info, env, .. } = ctx; @@ -321,11 +331,23 @@ fn execute_claim(ctx: ExecuteContext, validator: Option) -> Result Result Result { +pub fn reply(deps: DepsMut, env: Env, msg: Reply) -> Result { match ReplyId::from_repr(msg.id) { Some(ReplyId::ValidatorUnstake) => on_validator_unstake(deps, msg), + Some(ReplyId::RestakeReward) => on_restake_reward(deps, env, msg), _ => Ok(Response::default()), } } @@ -476,3 +499,30 @@ pub fn on_validator_unstake(deps: DepsMut, msg: Reply) -> Result Result { + match msg.result { + cosmwasm_std::SubMsgResult::Ok(_) => { + let restaking_queue = RESTAKING_QUEUE.load(deps.storage)?; + RESTAKING_QUEUE.remove(deps.storage); + + let res = execute_stake( + ExecuteContext { + deps, + info: MessageInfo { + sender: restaking_queue.delegator, + funds: restaking_queue.accumulated_rewards, + }, + env, + amp_ctx: None, + }, + Some(Addr::unchecked(restaking_queue.validator)), + )?; + Ok(res.add_attribute("action", "restake-reward")) + } + cosmwasm_std::SubMsgResult::Err(e) => { + RESTAKING_QUEUE.remove(deps.storage); + Err(ContractError::new(e.as_str())) + } + } +} diff --git a/contracts/finance/andromeda-validator-staking/src/mock.rs b/contracts/finance/andromeda-validator-staking/src/mock.rs index bfe78df31..e5c131acb 100644 --- a/contracts/finance/andromeda-validator-staking/src/mock.rs +++ b/contracts/finance/andromeda-validator-staking/src/mock.rs @@ -109,7 +109,10 @@ pub fn mock_execute_unstake(validator: Option, amount: Option) -> } pub fn mock_execute_claim_reward(validator: Option) -> ExecuteMsg { - ExecuteMsg::Claim { validator } + ExecuteMsg::Claim { + validator, + restake: None, + } } pub fn mock_execute_withdraw_fund( diff --git a/contracts/finance/andromeda-validator-staking/src/state.rs b/contracts/finance/andromeda-validator-staking/src/state.rs index 774ff1681..578f23f5b 100644 --- a/contracts/finance/andromeda-validator-staking/src/state.rs +++ b/contracts/finance/andromeda-validator-staking/src/state.rs @@ -1,8 +1,10 @@ use andromeda_finance::validator_staking::UnstakingTokens; use cw_storage_plus::Item; -use cosmwasm_std::Addr; +use cosmwasm_std::{Addr, FullDelegation}; pub const DEFAULT_VALIDATOR: Item = Item::new("default_validator"); pub const UNSTAKING_QUEUE: Item> = Item::new("unstaking_queue"); + +pub const RESTAKING_QUEUE: Item = Item::new("restaking_queue"); diff --git a/contracts/finance/andromeda-validator-staking/src/testing/tests.rs b/contracts/finance/andromeda-validator-staking/src/testing/tests.rs index d319a92b8..d1b61746f 100644 --- a/contracts/finance/andromeda-validator-staking/src/testing/tests.rs +++ b/contracts/finance/andromeda-validator-staking/src/testing/tests.rs @@ -167,6 +167,7 @@ fn test_unauthorized_claim() { let msg = ExecuteMsg::Claim { validator: Some(valid_validator.clone()), + restake: None, }; let info = mock_info(ANYONE, &[coin(100, "uandr")]); diff --git a/ibc-tests/tests/validator_staking.rs b/ibc-tests/tests/validator_staking.rs index 9e2d5e3b8..5bb2361c9 100644 --- a/ibc-tests/tests/validator_staking.rs +++ b/ibc-tests/tests/validator_staking.rs @@ -91,6 +91,7 @@ fn test_validator_staking() { let claim_msg = validator_staking::ExecuteMsg::Claim { validator: Some(Addr::unchecked(default_validator.address.to_string())), + restake: None, }; validator_staking_contract .execute(&claim_msg, None) @@ -176,6 +177,7 @@ fn test_kicked_validator() { let claim_msg = validator_staking::ExecuteMsg::Claim { validator: Some(Addr::unchecked(kicked_validator.address.to_string())), + restake: None, }; validator_staking_contract .execute(&claim_msg, None) diff --git a/packages/andromeda-finance/src/validator_staking.rs b/packages/andromeda-finance/src/validator_staking.rs index f9f1798de..9b8428828 100644 --- a/packages/andromeda-finance/src/validator_staking.rs +++ b/packages/andromeda-finance/src/validator_staking.rs @@ -27,6 +27,8 @@ pub enum ExecuteMsg { }, Claim { validator: Option, + /// Defaults to false + restake: Option, }, WithdrawFunds { denom: Option, From 90d9a63488da554ce0e1689f88d875a2af265f40 Mon Sep 17 00:00:00 2001 From: Joe Monem Date: Mon, 18 Nov 2024 09:42:12 +0200 Subject: [PATCH 12/20] fix: redelgation amount adjustment --- .../andromeda-validator-staking/src/contract.rs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/contracts/finance/andromeda-validator-staking/src/contract.rs b/contracts/finance/andromeda-validator-staking/src/contract.rs index 8b3be23a0..01297cf08 100644 --- a/contracts/finance/andromeda-validator-staking/src/contract.rs +++ b/contracts/finance/andromeda-validator-staking/src/contract.rs @@ -184,22 +184,25 @@ fn execute_redelegate( }; let redelegation_amount = match amount { Some(amount) => { - if amount > full_delegation.amount.amount { + if amount > full_delegation.can_redelegate.amount { return Err(ContractError::InvalidRedelegationAmount { amount: amount.to_string(), - max: full_delegation.amount.amount.to_string(), + max: full_delegation.can_redelegate.amount.to_string(), }); } amount } - None => full_delegation.amount.amount, + None => full_delegation.can_redelegate.amount, }; let res = Response::new() .add_message(StakingMsg::Redelegate { src_validator: src_validator.clone().into_string(), dst_validator: dst_validator.clone().into_string(), - amount: coin(redelegation_amount.u128(), full_delegation.amount.denom), + amount: coin( + redelegation_amount.u128(), + full_delegation.can_redelegate.denom, + ), }) .add_attribute("action", "redelegation") .add_attribute("from", src_validator.to_string()) From 4cbddbbdfc9632bbdb218768ef6c6983946afad4 Mon Sep 17 00:00:00 2001 From: Joe Monem Date: Mon, 18 Nov 2024 11:01:28 +0200 Subject: [PATCH 13/20] fix: unstaking queue --- .../andromeda-validator-staking/src/contract.rs | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/contracts/finance/andromeda-validator-staking/src/contract.rs b/contracts/finance/andromeda-validator-staking/src/contract.rs index 01297cf08..d9463320c 100644 --- a/contracts/finance/andromeda-validator-staking/src/contract.rs +++ b/contracts/finance/andromeda-validator-staking/src/contract.rs @@ -260,12 +260,11 @@ fn execute_unstake( amount: fund.clone(), }); - let unstaking_queue = UNSTAKING_QUEUE - .load(deps.storage) - .unwrap_or(vec![UnstakingTokens { - fund, - payout_at: Timestamp::default(), - }]); + let mut unstaking_queue = UNSTAKING_QUEUE.load(deps.storage).unwrap_or_default(); + unstaking_queue.push(UnstakingTokens { + fund, + payout_at: Timestamp::default(), + }); UNSTAKING_QUEUE.save(deps.storage, &unstaking_queue)?; From 1fc60461282a3968adf7e1a756e5c99ce3a8d866 Mon Sep 17 00:00:00 2001 From: Joe Monem Date: Mon, 18 Nov 2024 11:03:48 +0200 Subject: [PATCH 14/20] fix: ensure sender in redelegate is contract owner --- .../andromeda-validator-staking/src/contract.rs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/contracts/finance/andromeda-validator-staking/src/contract.rs b/contracts/finance/andromeda-validator-staking/src/contract.rs index d9463320c..14f9f7925 100644 --- a/contracts/finance/andromeda-validator-staking/src/contract.rs +++ b/contracts/finance/andromeda-validator-staking/src/contract.rs @@ -160,7 +160,16 @@ fn execute_redelegate( dst_validator: Addr, amount: Option, ) -> Result { - let ExecuteContext { deps, env, .. } = ctx; + let ExecuteContext { + deps, env, info, .. + } = ctx; + + // Ensure sender is the contract owner + ensure!( + ADOContract::default().is_contract_owner(deps.storage, info.sender.as_str())?, + ContractError::Unauthorized {} + ); + let src_validator = match src_validator { Some(addr) => { is_validator(&deps, &addr)?; From d87cb9a76e5893aca23523808113c40655f87f36 Mon Sep 17 00:00:00 2001 From: Joe Monem Date: Mon, 18 Nov 2024 11:18:53 +0200 Subject: [PATCH 15/20] test: validator redelegate --- .../andromeda-validator-staking/src/mock.rs | 24 ++++ tests-integration/tests/validator_staking.rs | 114 ++++++++++++++++++ 2 files changed, 138 insertions(+) diff --git a/contracts/finance/andromeda-validator-staking/src/mock.rs b/contracts/finance/andromeda-validator-staking/src/mock.rs index e5c131acb..541662574 100644 --- a/contracts/finance/andromeda-validator-staking/src/mock.rs +++ b/contracts/finance/andromeda-validator-staking/src/mock.rs @@ -26,6 +26,18 @@ impl MockValidatorStaking { self.execute(app, &msg, sender, &funds) } + pub fn execute_redelegate( + &self, + app: &mut MockApp, + sender: Addr, + src_validator: Option, + dst_validator: Addr, + amount: Option, + ) -> ExecuteResult { + let msg = mock_execute_redelegate(src_validator, dst_validator, amount); + self.execute(app, &msg, sender, &vec![]) + } + pub fn execute_unstake( &self, app: &mut MockApp, @@ -104,6 +116,18 @@ pub fn mock_execute_stake(validator: Option) -> ExecuteMsg { ExecuteMsg::Stake { validator } } +pub fn mock_execute_redelegate( + src_validator: Option, + dst_validator: Addr, + amount: Option, +) -> ExecuteMsg { + ExecuteMsg::Redelegate { + src_validator, + dst_validator, + amount, + } +} + pub fn mock_execute_unstake(validator: Option, amount: Option) -> ExecuteMsg { ExecuteMsg::Unstake { validator, amount } } diff --git a/tests-integration/tests/validator_staking.rs b/tests-integration/tests/validator_staking.rs index 16a769cf8..ecd4fb383 100644 --- a/tests-integration/tests/validator_staking.rs +++ b/tests-integration/tests/validator_staking.rs @@ -162,6 +162,120 @@ fn test_validator_stake() { assert_eq!(owner_balance, coin(1050, "TOKEN")); } +#[test] +fn test_validator_redelegate() { + let mut router = mock_app(Some(vec!["TOKEN"])); + + let andr = MockAndromedaBuilder::new(&mut router, "admin") + .with_wallets(vec![("owner", vec![coin(1000, "TOKEN")])]) + .with_contracts(vec![ + ("app-contract", mock_andromeda_app()), + ("validator-staking", mock_andromeda_validator_staking()), + ]) + .build(&mut router); + let owner = andr.get_wallet("owner"); + let validator_1 = router.api().addr_make("validator1"); + + let validator_staking_init_msg = mock_validator_staking_instantiate_msg( + validator_1.clone(), + None, + andr.kernel.addr().to_string(), + ); + + let validator_staking_component = AppComponent::new( + "staking".to_string(), + "validator-staking".to_string(), + to_json_binary(&validator_staking_init_msg).unwrap(), + ); + + let app_components = vec![validator_staking_component.clone()]; + let app = MockAppContract::instantiate( + andr.get_code_id(&mut router, "app-contract"), + owner, + &mut router, + "Validator Staking App", + app_components, + andr.kernel.addr(), + Some(owner.to_string()), + ); + + let validator_staking: MockValidatorStaking = + app.query_ado_by_component_name(&router, validator_staking_component.name); + + let funds = vec![coin(1000, "TOKEN")]; + + validator_staking + .execute_stake(&mut router, owner.clone(), None, funds) + .unwrap(); + + let stake_info = validator_staking + .query_staked_tokens(&router, None) + .unwrap(); + assert_eq!(stake_info.validator, validator_1.to_string()); + + // Testing when there is no reward to claim + // TODO: These errors cant be downcast anymore? + let _err = validator_staking + .execute_claim_reward(&mut router, owner.clone(), Some(validator_1.clone())) + .unwrap_err(); + // assert_eq!(may_err.unwrap(), &expected_err); + + // wait 1/2 year + router.set_block(BlockInfo { + height: router.block_info().height, + time: router + .block_info() + .time + .plus_seconds(60 * 60 * 24 * 365 / 2), + chain_id: router.block_info().chain_id, + }); + + validator_staking + .execute_claim_reward(&mut router, owner.clone(), Some(validator_1)) + .unwrap(); + + // Default APR 10% by cw-multi-test -> StakingInfo + // should now have 1000 * 10% / 2 - 0% commission = 50 tokens reward + let contract_balance = router + .wrap() + .query_balance(validator_staking.addr(), "TOKEN") + .unwrap(); + assert_eq!(contract_balance, coin(50, "TOKEN")); + + // Redelegate // + let validator_2 = router.api().addr_make("validator2"); + + // Redelegate with invalid amount + let err = validator_staking + .execute_redelegate( + &mut router, + owner.clone(), + None, + validator_2.clone(), + Some(Uint128::new(10000)), + ) + .unwrap_err() + .downcast::() + .unwrap(); + assert_eq!( + err, + ContractError::InvalidRedelegationAmount { + amount: "10000".to_string(), + max: "1000".to_string() + } + ); + + validator_staking + .execute_redelegate(&mut router, owner.clone(), None, validator_2.clone(), None) + .unwrap(); + + let stake_info = validator_staking + .query_staked_tokens(&router, Some(validator_2.clone())) + .unwrap(); + assert_eq!(stake_info.validator, validator_2.to_string()); + assert_eq!(stake_info.amount, coin(1000, "TOKEN")); +} + #[test] fn test_validator_stake_and_unstake_specific_amount() { let mut router = mock_app(Some(vec!["TOKEN"])); From e23d293bd52a15739d8dcb4b0323166bc337a8a5 Mon Sep 17 00:00:00 2001 From: Joe Monem Date: Mon, 18 Nov 2024 11:19:47 +0200 Subject: [PATCH 16/20] test: validator redelegate unauthorized --- tests-integration/tests/validator_staking.rs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/tests-integration/tests/validator_staking.rs b/tests-integration/tests/validator_staking.rs index ecd4fb383..78848c30e 100644 --- a/tests-integration/tests/validator_staking.rs +++ b/tests-integration/tests/validator_staking.rs @@ -265,6 +265,20 @@ fn test_validator_redelegate() { } ); + // Redelegate with invalid sender + let err = validator_staking + .execute_redelegate( + &mut router, + Addr::unchecked("other"), + None, + validator_2.clone(), + None, + ) + .unwrap_err() + .downcast::() + .unwrap(); + assert_eq!(err, ContractError::Unauthorized {}); + validator_staking .execute_redelegate(&mut router, owner.clone(), None, validator_2.clone(), None) .unwrap(); From faef9be2fd4146c5fe1e59a7b7aae551def591dc Mon Sep 17 00:00:00 2001 From: Joe Monem Date: Mon, 18 Nov 2024 11:27:36 +0200 Subject: [PATCH 17/20] test: restake --- .../andromeda-validator-staking/src/mock.rs | 10 +-- tests-integration/tests/validator_staking.rs | 83 +++++++++++++++++-- 2 files changed, 81 insertions(+), 12 deletions(-) diff --git a/contracts/finance/andromeda-validator-staking/src/mock.rs b/contracts/finance/andromeda-validator-staking/src/mock.rs index 541662574..32fd18433 100644 --- a/contracts/finance/andromeda-validator-staking/src/mock.rs +++ b/contracts/finance/andromeda-validator-staking/src/mock.rs @@ -54,8 +54,9 @@ impl MockValidatorStaking { app: &mut MockApp, sender: Addr, validator: Option, + restake: Option, ) -> ExecuteResult { - let msg = mock_execute_claim_reward(validator); + let msg = mock_execute_claim_reward(validator, restake); self.execute(app, &msg, sender, &[]) } @@ -132,11 +133,8 @@ pub fn mock_execute_unstake(validator: Option, amount: Option) -> ExecuteMsg::Unstake { validator, amount } } -pub fn mock_execute_claim_reward(validator: Option) -> ExecuteMsg { - ExecuteMsg::Claim { - validator, - restake: None, - } +pub fn mock_execute_claim_reward(validator: Option, restake: Option) -> ExecuteMsg { + ExecuteMsg::Claim { validator, restake } } pub fn mock_execute_withdraw_fund( diff --git a/tests-integration/tests/validator_staking.rs b/tests-integration/tests/validator_staking.rs index 78848c30e..987c9b3af 100644 --- a/tests-integration/tests/validator_staking.rs +++ b/tests-integration/tests/validator_staking.rs @@ -69,7 +69,7 @@ fn test_validator_stake() { // Testing when there is no reward to claim // TODO: These errors cant be downcast anymore? let _err = validator_staking - .execute_claim_reward(&mut router, owner.clone(), Some(validator_1.clone())) + .execute_claim_reward(&mut router, owner.clone(), Some(validator_1.clone()), None) .unwrap_err(); // assert_eq!(may_err.unwrap(), &expected_err); @@ -84,7 +84,7 @@ fn test_validator_stake() { }); validator_staking - .execute_claim_reward(&mut router, owner.clone(), Some(validator_1)) + .execute_claim_reward(&mut router, owner.clone(), Some(validator_1), None) .unwrap(); // Default APR 10% by cw-multi-test -> StakingInfo @@ -162,6 +162,77 @@ fn test_validator_stake() { assert_eq!(owner_balance, coin(1050, "TOKEN")); } +#[test] +fn test_restake() { + let mut router = mock_app(Some(vec!["TOKEN"])); + + let andr = MockAndromedaBuilder::new(&mut router, "admin") + .with_wallets(vec![("owner", vec![coin(1000, "TOKEN")])]) + .with_contracts(vec![ + ("app-contract", mock_andromeda_app()), + ("validator-staking", mock_andromeda_validator_staking()), + ]) + .build(&mut router); + let owner = andr.get_wallet("owner"); + let validator_1 = router.api().addr_make("validator1"); + + let validator_staking_init_msg = mock_validator_staking_instantiate_msg( + validator_1.clone(), + None, + andr.kernel.addr().to_string(), + ); + + let validator_staking_component = AppComponent::new( + "staking".to_string(), + "validator-staking".to_string(), + to_json_binary(&validator_staking_init_msg).unwrap(), + ); + + let app_components = vec![validator_staking_component.clone()]; + let app = MockAppContract::instantiate( + andr.get_code_id(&mut router, "app-contract"), + owner, + &mut router, + "Validator Staking App", + app_components, + andr.kernel.addr(), + Some(owner.to_string()), + ); + + let validator_staking: MockValidatorStaking = + app.query_ado_by_component_name(&router, validator_staking_component.name); + + let funds = vec![coin(1000, "TOKEN")]; + + validator_staking + .execute_stake(&mut router, owner.clone(), None, funds) + .unwrap(); + + let stake_info = validator_staking + .query_staked_tokens(&router, None) + .unwrap(); + assert_eq!(stake_info.validator, validator_1.to_string()); + + // wait 1/2 year + router.set_block(BlockInfo { + height: router.block_info().height, + time: router + .block_info() + .time + .plus_seconds(60 * 60 * 24 * 365 / 2), + chain_id: router.block_info().chain_id, + }); + + validator_staking + .execute_claim_reward(&mut router, owner.clone(), Some(validator_1), Some(true)) + .unwrap(); + + let stake_info = validator_staking + .query_staked_tokens(&router, None) + .unwrap(); + assert_eq!(stake_info.amount, coin(1050, "TOKEN")); +} + #[test] fn test_validator_redelegate() { let mut router = mock_app(Some(vec!["TOKEN"])); @@ -216,7 +287,7 @@ fn test_validator_redelegate() { // Testing when there is no reward to claim // TODO: These errors cant be downcast anymore? let _err = validator_staking - .execute_claim_reward(&mut router, owner.clone(), Some(validator_1.clone())) + .execute_claim_reward(&mut router, owner.clone(), Some(validator_1.clone()), None) .unwrap_err(); // assert_eq!(may_err.unwrap(), &expected_err); @@ -231,7 +302,7 @@ fn test_validator_redelegate() { }); validator_staking - .execute_claim_reward(&mut router, owner.clone(), Some(validator_1)) + .execute_claim_reward(&mut router, owner.clone(), Some(validator_1), None) .unwrap(); // Default APR 10% by cw-multi-test -> StakingInfo @@ -343,7 +414,7 @@ fn test_validator_stake_and_unstake_specific_amount() { // Testing when there is no reward to claim let _err = validator_staking - .execute_claim_reward(&mut router, owner.clone(), Some(validator_1.clone())) + .execute_claim_reward(&mut router, owner.clone(), Some(validator_1.clone()), None) .unwrap_err(); // assert_eq!(may_err.unwrap(), &expected_err); @@ -358,7 +429,7 @@ fn test_validator_stake_and_unstake_specific_amount() { }); validator_staking - .execute_claim_reward(&mut router, owner.clone(), Some(validator_1)) + .execute_claim_reward(&mut router, owner.clone(), Some(validator_1), None) .unwrap(); // Default APR 10% by cw-multi-test -> StakingInfo From 7e2bb0cba5c315958babf0768ba755511614897b Mon Sep 17 00:00:00 2001 From: Joe Monem Date: Mon, 18 Nov 2024 11:31:29 +0200 Subject: [PATCH 18/20] ref: only owner can choose to restake --- .../finance/andromeda-validator-staking/src/contract.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/contracts/finance/andromeda-validator-staking/src/contract.rs b/contracts/finance/andromeda-validator-staking/src/contract.rs index 14f9f7925..3a327dfdc 100644 --- a/contracts/finance/andromeda-validator-staking/src/contract.rs +++ b/contracts/finance/andromeda-validator-staking/src/contract.rs @@ -345,6 +345,11 @@ fn execute_claim( let restake = restake.unwrap_or(false); // Only one denom is allowed to be restaked at a time let res = if restake && res.accumulated_rewards.len() == 1 { + // Only the contract owner can decide to restake + ensure!( + ADOContract::default().is_contract_owner(deps.storage, info.sender.as_str())?, + ContractError::Unauthorized {} + ); RESTAKING_QUEUE.save(deps.storage, &res)?; Response::new() .add_submessage(SubMsg::reply_always( From 8496f31bf585e0c6e8a5a612dfde9008eb33df1d Mon Sep 17 00:00:00 2001 From: Joe Monem Date: Mon, 18 Nov 2024 11:36:12 +0200 Subject: [PATCH 19/20] chore: linting --- contracts/finance/andromeda-validator-staking/src/mock.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/finance/andromeda-validator-staking/src/mock.rs b/contracts/finance/andromeda-validator-staking/src/mock.rs index 32fd18433..18c5e8cec 100644 --- a/contracts/finance/andromeda-validator-staking/src/mock.rs +++ b/contracts/finance/andromeda-validator-staking/src/mock.rs @@ -35,7 +35,7 @@ impl MockValidatorStaking { amount: Option, ) -> ExecuteResult { let msg = mock_execute_redelegate(src_validator, dst_validator, amount); - self.execute(app, &msg, sender, &vec![]) + self.execute(app, &msg, sender, &[]) } pub fn execute_unstake( From e8469e6da78bc9d9860f666dc10c6681359f2b0c Mon Sep 17 00:00:00 2001 From: Joe Monem Date: Mon, 18 Nov 2024 16:11:37 +0200 Subject: [PATCH 20/20] chore: changelog entry --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index aba018ff4..40224b653 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -51,6 +51,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Added Denom Validation for Rates [(#568)](https://github.com/andromedaprotocol/andromeda-core/pull/568) - Added BuyNow option for Auction [(#533)](https://github.com/andromedaprotocol/andromeda-core/pull/533) - Include ADOBase Version in Schema [(#574)](https://github.com/andromedaprotocol/andromeda-core/pull/574) +- Added Restake and Redelegate to Validator Staking [(#622)](https://github.com/andromedaprotocol/andromeda-core/pull/622) ### Changed