Skip to content

Commit

Permalink
Improve unstaking_duration validation reuse
Browse files Browse the repository at this point in the history
  • Loading branch information
Jake Hartnell committed Sep 5, 2023
1 parent c2c230d commit 318cea5
Show file tree
Hide file tree
Showing 11 changed files with 95 additions and 99 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions contracts/staking/cw20-stake/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ thiserror = { workspace = true }
cw-paginate-storage = { workspace = true }
cw-ownable = { workspace = true }
dao-hooks = { workspace = true }
dao-voting = { workspace = true }

cw20-stake-v1 = { workspace = true, features = ["library"] }
cw-utils-v1 = { workspace = true }
Expand Down
44 changes: 13 additions & 31 deletions contracts/staking/cw20-stake/src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,8 @@ use cosmwasm_std::{
from_binary, to_binary, Addr, Binary, Deps, DepsMut, Empty, Env, MessageInfo, Response,
StdError, StdResult, Uint128,
};

use cw20::{Cw20ReceiveMsg, TokenInfoResponse};

use crate::math;
use crate::msg::{
ExecuteMsg, GetHooksResponse, InstantiateMsg, ListStakersResponse, MigrateMsg, QueryMsg,
ReceiveMsg, StakedBalanceAtHeightResponse, StakedValueResponse, StakerBalanceResponse,
TotalStakedAtHeightResponse, TotalValueResponse,
};
use crate::state::{
Config, BALANCE, CLAIMS, CONFIG, HOOKS, MAX_CLAIMS, STAKED_BALANCES, STAKED_TOTAL,
};
use crate::ContractError;
use cw2::{get_contract_version, set_contract_version, ContractVersion};
use cw20::{Cw20ReceiveMsg, TokenInfoResponse};
pub use cw20_base::allowances::{
execute_burn_from, execute_decrease_allowance, execute_increase_allowance, execute_send_from,
execute_transfer_from, query_allowance,
Expand All @@ -32,28 +20,22 @@ pub use cw20_base::enumerable::{query_all_accounts, query_owner_allowances};
use cw_controllers::ClaimsResponse;
use cw_utils::Duration;
use dao_hooks::stake::{stake_hook_msgs, unstake_hook_msgs};
use dao_voting::duration::validate_duration;

use crate::math;
use crate::msg::{
ExecuteMsg, GetHooksResponse, InstantiateMsg, ListStakersResponse, MigrateMsg, QueryMsg,
ReceiveMsg, StakedBalanceAtHeightResponse, StakedValueResponse, StakerBalanceResponse,
TotalStakedAtHeightResponse, TotalValueResponse,
};
use crate::state::{
Config, BALANCE, CLAIMS, CONFIG, HOOKS, MAX_CLAIMS, STAKED_BALANCES, STAKED_TOTAL,
};
use crate::ContractError;

pub(crate) const CONTRACT_NAME: &str = "crates.io:cw20-stake";
pub(crate) const CONTRACT_VERSION: &str = env!("CARGO_PKG_VERSION");

fn validate_duration(duration: Option<Duration>) -> Result<(), ContractError> {
if let Some(unstaking_duration) = duration {
match unstaking_duration {
Duration::Height(height) => {
if height == 0 {
return Err(ContractError::InvalidUnstakingDuration {});
}
}
Duration::Time(time) => {
if time == 0 {
return Err(ContractError::InvalidUnstakingDuration {});
}
}
}
}
Ok(())
}

#[cfg_attr(not(feature = "library"), entry_point)]
pub fn instantiate(
deps: DepsMut,
Expand Down
31 changes: 21 additions & 10 deletions contracts/staking/cw20-stake/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,29 +5,40 @@ use thiserror::Error;
pub enum ContractError {
#[error(transparent)]
Std(#[from] StdError),

#[error(transparent)]
Cw20Error(#[from] cw20_base::ContractError),

#[error(transparent)]
Ownership(#[from] cw_ownable::OwnershipError),

#[error(transparent)]
HookError(#[from] cw_hooks::HookError),

#[error("Provided cw20 errored in response to TokenInfo query")]
InvalidCw20 {},
#[error("Nothing to claim")]
NothingToClaim {},
#[error("Nothing to unstake")]
NothingStaked {},
#[error(transparent)]
UnstakingDurationError(#[from] dao_voting::duration::UnstakingDurationError),

#[error("can not migrate. current version is up to date")]
AlreadyMigrated {},

#[error("Unstaking this amount violates the invariant: (cw20 total_supply <= 2^128)")]
Cw20InvaraintViolation {},

#[error("Can not unstake more than has been staked")]
ImpossibleUnstake {},

#[error("Provided cw20 errored in response to TokenInfo query")]
InvalidCw20 {},

#[error("Invalid token")]
InvalidToken { received: Addr, expected: Addr },

#[error("Nothing to claim")]
NothingToClaim {},

#[error("Nothing to unstake")]
NothingStaked {},

#[error("Too many outstanding claims. Claim some tokens before unstaking more.")]
TooManyClaims {},
#[error("Invalid unstaking duration, unstaking duration cannot be 0")]
InvalidUnstakingDuration {},
#[error("can not migrate. current version is up to date")]
AlreadyMigrated {},
}
31 changes: 18 additions & 13 deletions contracts/staking/cw20-stake/src/tests.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
use anyhow::Result as AnyResult;
use cosmwasm_std::testing::{mock_dependencies, mock_env, mock_info};
use cosmwasm_std::{to_binary, Addr, Empty, MessageInfo, Uint128, WasmMsg};
use cw20::Cw20Coin;
use cw_controllers::{Claim, ClaimsResponse};
use cw_multi_test::{next_block, App, AppResponse, Contract, ContractWrapper, Executor};
use cw_ownable::{Action, Ownership, OwnershipError};
use cw_utils::Duration;
use cw_utils::Expiration::AtHeight;
use dao_voting::duration::UnstakingDurationError;
use std::borrow::BorrowMut;

use crate::msg::{
Expand All @@ -7,20 +17,9 @@ use crate::msg::{
};
use crate::state::{Config, MAX_CLAIMS};
use crate::ContractError;
use cosmwasm_std::testing::{mock_dependencies, mock_env, mock_info};
use cosmwasm_std::{to_binary, Addr, Empty, MessageInfo, Uint128, WasmMsg};
use cw20::Cw20Coin;
use cw_ownable::{Action, Ownership, OwnershipError};
use cw_utils::Duration;

use cw_multi_test::{next_block, App, AppResponse, Contract, ContractWrapper, Executor};

use anyhow::Result as AnyResult;
use cw20_stake_v1 as v1;

use cw_controllers::{Claim, ClaimsResponse};
use cw_utils::Expiration::AtHeight;

const ADDR1: &str = "addr0001";
const ADDR2: &str = "addr0002";
const ADDR3: &str = "addr0003";
Expand Down Expand Up @@ -273,14 +272,20 @@ fn test_update_config() {
.unwrap_err()
.downcast()
.unwrap();
assert_eq!(err, ContractError::InvalidUnstakingDuration {});
assert_eq!(
err,
ContractError::UnstakingDurationError(UnstakingDurationError::InvalidUnstakingDuration {})
);

let info = mock_info(OWNER, &[]);
let err: ContractError = update_config(&mut app, &staking_addr, info, Some(Duration::Time(0)))
.unwrap_err()
.downcast()
.unwrap();
assert_eq!(err, ContractError::InvalidUnstakingDuration {});
assert_eq!(
err,
ContractError::UnstakingDurationError(UnstakingDurationError::InvalidUnstakingDuration {})
);
}

#[test]
Expand Down
23 changes: 4 additions & 19 deletions contracts/voting/dao-voting-native-staked/src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,10 @@ use dao_hooks::stake::{stake_hook_msgs, unstake_hook_msgs};
use dao_interface::voting::{
IsActiveResponse, TotalPowerAtHeightResponse, VotingPowerAtHeightResponse,
};
use dao_voting::threshold::{ActiveThreshold, ActiveThresholdResponse};
use dao_voting::{
duration::validate_duration,
threshold::{ActiveThreshold, ActiveThresholdResponse},
};

use crate::error::ContractError;
use crate::msg::{
Expand All @@ -29,24 +32,6 @@ pub(crate) const CONTRACT_VERSION: &str = env!("CARGO_PKG_VERSION");
// when using active threshold with percent
const PRECISION_FACTOR: u128 = 10u128.pow(9);

fn validate_duration(duration: Option<Duration>) -> Result<(), ContractError> {
if let Some(unstaking_duration) = duration {
match unstaking_duration {
Duration::Height(height) => {
if height == 0 {
return Err(ContractError::InvalidUnstakingDuration {});
}
}
Duration::Time(time) => {
if time == 0 {
return Err(ContractError::InvalidUnstakingDuration {});
}
}
}
}
Ok(())
}

#[cfg_attr(not(feature = "library"), entry_point)]
pub fn instantiate(
deps: DepsMut,
Expand Down
6 changes: 3 additions & 3 deletions contracts/voting/dao-voting-native-staked/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,15 @@ pub enum ContractError {
#[error(transparent)]
HookError(#[from] cw_hooks::HookError),

#[error(transparent)]
UnstakingDurationError(#[from] dao_voting::duration::UnstakingDurationError),

#[error("Unauthorized")]
Unauthorized {},

#[error("Denom does not exist on chain")]
InvalidDenom {},

#[error("Invalid unstaking duration, unstaking duration cannot be 0")]
InvalidUnstakingDuration {},

#[error("Nothing to claim")]
NothingToClaim {},

Expand Down
24 changes: 4 additions & 20 deletions contracts/voting/dao-voting-token-factory-staked/src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,12 @@ use dao_hooks::stake::{stake_hook_msgs, unstake_hook_msgs};
use dao_interface::voting::{
IsActiveResponse, TotalPowerAtHeightResponse, VotingPowerAtHeightResponse,
};
use dao_voting::threshold::{ActiveThreshold, ActiveThresholdResponse};
use dao_voting::{
duration::validate_duration,
threshold::{ActiveThreshold, ActiveThresholdResponse},
};

use crate::error::ContractError;

use crate::msg::{
DenomResponse, ExecuteMsg, GetHooksResponse, InitialBalance, InstantiateMsg,
ListStakersResponse, MigrateMsg, QueryMsg, StakerBalanceResponse, TokenInfo,
Expand All @@ -42,24 +44,6 @@ const INSTANTIATE_TOKEN_FACTORY_ISSUER_REPLY_ID: u64 = 0;
// when using active threshold with percent
const PRECISION_FACTOR: u128 = 10u128.pow(9);

fn validate_duration(duration: Option<Duration>) -> Result<(), ContractError> {
if let Some(unstaking_duration) = duration {
match unstaking_duration {
Duration::Height(height) => {
if height == 0 {
return Err(ContractError::InvalidUnstakingDuration {});
}
}
Duration::Time(time) => {
if time == 0 {
return Err(ContractError::InvalidUnstakingDuration {});
}
}
}
}
Ok(())
}

#[cfg_attr(not(feature = "library"), entry_point)]
pub fn instantiate(
deps: DepsMut,
Expand Down
6 changes: 3 additions & 3 deletions contracts/voting/dao-voting-token-factory-staked/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ pub enum ContractError {
#[error(transparent)]
HookError(#[from] cw_hooks::HookError),

#[error(transparent)]
UnstakingDurationError(#[from] dao_voting::duration::UnstakingDurationError),

#[error("Absolute count threshold cannot be greater than the total token supply")]
InvalidAbsoluteCount {},

Expand All @@ -28,9 +31,6 @@ pub enum ContractError {
#[error("Can only unstake less than or equal to the amount you have staked")]
InvalidUnstakeAmount {},

#[error("Invalid unstaking duration, unstaking duration cannot be 0")]
InvalidUnstakingDuration {},

#[error("Nothing to claim")]
NothingToClaim {},

Expand Down
26 changes: 26 additions & 0 deletions packages/dao-voting/src/duration.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
use cw_utils::Duration;
use thiserror::Error;

#[derive(Error, Debug, PartialEq, Eq)]
pub enum UnstakingDurationError {
#[error("Invalid unstaking duration, unstaking duration cannot be 0")]
InvalidUnstakingDuration {},
}

pub fn validate_duration(duration: Option<Duration>) -> Result<(), UnstakingDurationError> {
if let Some(unstaking_duration) = duration {
match unstaking_duration {
Duration::Height(height) => {
if height == 0 {
return Err(UnstakingDurationError::InvalidUnstakingDuration {});
}
}
Duration::Time(time) => {
if time == 0 {
return Err(UnstakingDurationError::InvalidUnstakingDuration {});
}

Check warning on line 21 in packages/dao-voting/src/duration.rs

View check run for this annotation

Codecov / codecov/patch

packages/dao-voting/src/duration.rs#L21

Added line #L21 was not covered by tests
}
}
}
Ok(())
}
1 change: 1 addition & 0 deletions packages/dao-voting/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#![doc = include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/README.md"))]

pub mod deposit;
pub mod duration;
pub mod error;
pub mod multiple_choice;
pub mod pre_propose;
Expand Down

0 comments on commit 318cea5

Please sign in to comment.